gemachain_runtime/
accounts.rs

1use crate::{
2    accounts_db::{
3        AccountShrinkThreshold, AccountsDb, AccountsDbConfig, BankHashInfo, ErrorCounters,
4        LoadHint, LoadedAccount, ScanStorageResult, ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS,
5        ACCOUNTS_DB_CONFIG_FOR_TESTING,
6    },
7    accounts_index::{AccountSecondaryIndexes, IndexKey, ScanResult},
8    ancestors::Ancestors,
9    bank::{
10        NonceRollbackFull, NonceRollbackInfo, RentDebits, TransactionCheckResult,
11        TransactionExecutionResult,
12    },
13    blockhash_queue::BlockhashQueue,
14    rent_collector::RentCollector,
15    system_instruction_processor::{get_system_account_kind, SystemAccountKind},
16};
17use dashmap::{
18    mapref::entry::Entry::{Occupied, Vacant},
19    DashMap,
20};
21use log::*;
22use rand::{thread_rng, Rng};
23use gemachain_sdk::{
24    account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
25    account_utils::StateMut,
26    bpf_loader_upgradeable::{self, UpgradeableLoaderState},
27    clock::{BankId, Slot, INITIAL_RENT_EPOCH},
28    feature_set::{self, FeatureSet},
29    fee_calculator::FeeCalculator,
30    genesis_config::ClusterType,
31    hash::Hash,
32    message::SanitizedMessage,
33    native_loader, nonce,
34    nonce::NONCED_TX_MARKER_IX_INDEX,
35    pubkey::Pubkey,
36    system_program, sysvar,
37    transaction::{Result, SanitizedTransaction, TransactionError},
38};
39use std::{
40    cmp::Reverse,
41    collections::{hash_map, BinaryHeap, HashMap, HashSet},
42    ops::RangeBounds,
43    path::PathBuf,
44    sync::{Arc, Mutex},
45};
46
47#[derive(Debug, Default, AbiExample)]
48pub struct AccountLocks {
49    write_locks: HashSet<Pubkey>,
50    readonly_locks: HashMap<Pubkey, u64>,
51}
52
53impl AccountLocks {
54    fn is_locked_readonly(&self, key: &Pubkey) -> bool {
55        self.readonly_locks
56            .get(key)
57            .map_or(false, |count| *count > 0)
58    }
59
60    fn is_locked_write(&self, key: &Pubkey) -> bool {
61        self.write_locks.contains(key)
62    }
63
64    fn insert_new_readonly(&mut self, key: &Pubkey) {
65        assert!(self.readonly_locks.insert(*key, 1).is_none());
66    }
67
68    fn lock_readonly(&mut self, key: &Pubkey) -> bool {
69        self.readonly_locks.get_mut(key).map_or(false, |count| {
70            *count += 1;
71            true
72        })
73    }
74
75    fn unlock_readonly(&mut self, key: &Pubkey) {
76        if let hash_map::Entry::Occupied(mut occupied_entry) = self.readonly_locks.entry(*key) {
77            let count = occupied_entry.get_mut();
78            *count -= 1;
79            if *count == 0 {
80                occupied_entry.remove_entry();
81            }
82        }
83    }
84
85    fn unlock_write(&mut self, key: &Pubkey) {
86        self.write_locks.remove(key);
87    }
88}
89
90/// This structure handles synchronization for db
91#[derive(Debug, AbiExample)]
92pub struct Accounts {
93    /// Single global AccountsDb
94    pub accounts_db: Arc<AccountsDb>,
95
96    /// set of read-only and writable accounts which are currently
97    /// being processed by banking/replay threads
98    pub(crate) account_locks: Mutex<AccountLocks>,
99}
100
101// for the load instructions
102pub type TransactionAccounts = Vec<(Pubkey, AccountSharedData)>;
103pub type TransactionRent = u64;
104pub type TransactionProgramIndices = Vec<Vec<usize>>;
105#[derive(PartialEq, Debug, Clone)]
106pub struct LoadedTransaction {
107    pub accounts: TransactionAccounts,
108    pub program_indices: TransactionProgramIndices,
109    pub rent: TransactionRent,
110    pub rent_debits: RentDebits,
111}
112
113pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceRollbackFull>);
114
115pub enum AccountAddressFilter {
116    Exclude, // exclude all addresses matching the filter
117    Include, // only include addresses matching the filter
118}
119
120impl Accounts {
121    pub fn default_for_tests() -> Self {
122        Self {
123            accounts_db: Arc::new(AccountsDb::default_for_tests()),
124            account_locks: Mutex::default(),
125        }
126    }
127
128    pub fn new_with_config_for_tests(
129        paths: Vec<PathBuf>,
130        cluster_type: &ClusterType,
131        account_indexes: AccountSecondaryIndexes,
132        caching_enabled: bool,
133        shrink_ratio: AccountShrinkThreshold,
134    ) -> Self {
135        Self::new_with_config(
136            paths,
137            cluster_type,
138            account_indexes,
139            caching_enabled,
140            shrink_ratio,
141            Some(ACCOUNTS_DB_CONFIG_FOR_TESTING),
142        )
143    }
144
145    pub fn new_with_config_for_benches(
146        paths: Vec<PathBuf>,
147        cluster_type: &ClusterType,
148        account_indexes: AccountSecondaryIndexes,
149        caching_enabled: bool,
150        shrink_ratio: AccountShrinkThreshold,
151    ) -> Self {
152        Self::new_with_config(
153            paths,
154            cluster_type,
155            account_indexes,
156            caching_enabled,
157            shrink_ratio,
158            Some(ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS),
159        )
160    }
161
162    pub fn new_with_config(
163        paths: Vec<PathBuf>,
164        cluster_type: &ClusterType,
165        account_indexes: AccountSecondaryIndexes,
166        caching_enabled: bool,
167        shrink_ratio: AccountShrinkThreshold,
168        accounts_db_config: Option<AccountsDbConfig>,
169    ) -> Self {
170        Self {
171            accounts_db: Arc::new(AccountsDb::new_with_config(
172                paths,
173                cluster_type,
174                account_indexes,
175                caching_enabled,
176                shrink_ratio,
177                accounts_db_config,
178            )),
179            account_locks: Mutex::new(AccountLocks::default()),
180        }
181    }
182
183    pub fn new_from_parent(parent: &Accounts, slot: Slot, parent_slot: Slot) -> Self {
184        let accounts_db = parent.accounts_db.clone();
185        accounts_db.set_hash(slot, parent_slot);
186        Self {
187            accounts_db,
188            account_locks: Mutex::new(AccountLocks::default()),
189        }
190    }
191
192    pub(crate) fn new_empty(accounts_db: AccountsDb) -> Self {
193        Self {
194            accounts_db: Arc::new(accounts_db),
195            account_locks: Mutex::new(AccountLocks::default()),
196        }
197    }
198
199    fn construct_instructions_account(
200        message: &SanitizedMessage,
201        is_owned_by_sysvar: bool,
202        demote_program_write_locks: bool,
203    ) -> AccountSharedData {
204        let mut data = message.serialize_instructions(demote_program_write_locks);
205        // add room for current instruction index.
206        data.resize(data.len() + 2, 0);
207        let owner = if is_owned_by_sysvar {
208            sysvar::id()
209        } else {
210            system_program::id()
211        };
212        AccountSharedData::from(Account {
213            data,
214            owner,
215            ..Account::default()
216        })
217    }
218
219    fn load_transaction(
220        &self,
221        ancestors: &Ancestors,
222        tx: &SanitizedTransaction,
223        fee: u64,
224        error_counters: &mut ErrorCounters,
225        rent_collector: &RentCollector,
226        feature_set: &FeatureSet,
227    ) -> Result<LoadedTransaction> {
228        // Copy all the accounts
229        let message = tx.message();
230        // NOTE: this check will never fail because `tx` is sanitized
231        if tx.signatures().is_empty() && fee != 0 {
232            Err(TransactionError::MissingSignatureForFee)
233        } else {
234            // There is no way to predict what program will execute without an error
235            // If a fee can pay for execution then the program will be scheduled
236            let mut payer_index = None;
237            let mut tx_rent: TransactionRent = 0;
238            let mut accounts = Vec::with_capacity(message.account_keys_len());
239            let mut account_deps = Vec::with_capacity(message.account_keys_len());
240            let mut rent_debits = RentDebits::default();
241            let rent_for_sysvars = feature_set.is_active(&feature_set::rent_for_sysvars::id());
242            let demote_program_write_locks =
243                feature_set.is_active(&feature_set::demote_program_write_locks::id());
244            let is_upgradeable_loader_present = is_upgradeable_loader_present(message);
245
246            for (i, key) in message.account_keys_iter().enumerate() {
247                let account = if !message.is_non_loader_key(i) {
248                    // Fill in an empty account for the program slots.
249                    AccountSharedData::default()
250                } else {
251                    if payer_index.is_none() {
252                        payer_index = Some(i);
253                    }
254
255                    if gemachain_sdk::sysvar::instructions::check_id(key) {
256                        Self::construct_instructions_account(
257                            message,
258                            feature_set
259                                .is_active(&feature_set::instructions_sysvar_owned_by_sysvar::id()),
260                            demote_program_write_locks,
261                        )
262                    } else {
263                        let (account, rent) = self
264                            .accounts_db
265                            .load_with_fixed_root(ancestors, key)
266                            .map(|(mut account, _)| {
267                                if message.is_writable(i, demote_program_write_locks) {
268                                    let rent_due = rent_collector.collect_from_existing_account(
269                                        key,
270                                        &mut account,
271                                        rent_for_sysvars,
272                                    );
273                                    (account, rent_due)
274                                } else {
275                                    (account, 0)
276                                }
277                            })
278                            .unwrap_or_default();
279
280                        if bpf_loader_upgradeable::check_id(account.owner()) {
281                            if demote_program_write_locks
282                                && message.is_writable(i, demote_program_write_locks)
283                                && !is_upgradeable_loader_present
284                            {
285                                error_counters.invalid_writable_account += 1;
286                                return Err(TransactionError::InvalidWritableAccount);
287                            }
288
289                            if account.executable() {
290                                // The upgradeable loader requires the derived ProgramData account
291                                if let Ok(UpgradeableLoaderState::Program {
292                                    programdata_address,
293                                }) = account.state()
294                                {
295                                    if let Some((programdata_account, _)) = self
296                                        .accounts_db
297                                        .load_with_fixed_root(ancestors, &programdata_address)
298                                    {
299                                        account_deps
300                                            .push((programdata_address, programdata_account));
301                                    } else {
302                                        error_counters.account_not_found += 1;
303                                        return Err(TransactionError::ProgramAccountNotFound);
304                                    }
305                                } else {
306                                    error_counters.invalid_program_for_execution += 1;
307                                    return Err(TransactionError::InvalidProgramForExecution);
308                                }
309                            }
310                        } else if account.executable()
311                            && demote_program_write_locks
312                            && message.is_writable(i, demote_program_write_locks)
313                        {
314                            error_counters.invalid_writable_account += 1;
315                            return Err(TransactionError::InvalidWritableAccount);
316                        }
317
318                        tx_rent += rent;
319                        rent_debits.push(key, rent, account.carats());
320
321                        account
322                    }
323                };
324                accounts.push((*key, account));
325            }
326            debug_assert_eq!(accounts.len(), message.account_keys_len());
327            // Appends the account_deps at the end of the accounts,
328            // this way they can be accessed in a uniform way.
329            // At places where only the accounts are needed,
330            // the account_deps are truncated using e.g:
331            // accounts.iter().take(message.account_keys.len())
332            accounts.append(&mut account_deps);
333
334            if let Some(payer_index) = payer_index {
335                if payer_index != 0 {
336                    warn!("Payer index should be 0! {:?}", tx);
337                }
338                let payer_account = &mut accounts[payer_index].1;
339                if payer_account.carats() == 0 {
340                    error_counters.account_not_found += 1;
341                    return Err(TransactionError::AccountNotFound);
342                }
343                let min_balance = match get_system_account_kind(payer_account).ok_or_else(|| {
344                    error_counters.invalid_account_for_fee += 1;
345                    TransactionError::InvalidAccountForFee
346                })? {
347                    SystemAccountKind::System => 0,
348                    SystemAccountKind::Nonce => {
349                        // Should we ever allow a fees charge to zero a nonce account's
350                        // balance. The state MUST be set to uninitialized in that case
351                        rent_collector.rent.minimum_balance(nonce::State::size())
352                    }
353                };
354
355                if payer_account.carats() < fee + min_balance {
356                    error_counters.insufficient_funds += 1;
357                    return Err(TransactionError::InsufficientFundsForFee);
358                }
359                payer_account
360                    .checked_sub_carats(fee)
361                    .map_err(|_| TransactionError::InsufficientFundsForFee)?;
362
363                let program_indices = message
364                    .instructions()
365                    .iter()
366                    .map(|instruction| {
367                        self.load_executable_accounts(
368                            ancestors,
369                            &mut accounts,
370                            instruction.program_id_index as usize,
371                            error_counters,
372                        )
373                    })
374                    .collect::<Result<Vec<Vec<usize>>>>()?;
375                Ok(LoadedTransaction {
376                    accounts,
377                    program_indices,
378                    rent: tx_rent,
379                    rent_debits,
380                })
381            } else {
382                error_counters.account_not_found += 1;
383                Err(TransactionError::AccountNotFound)
384            }
385        }
386    }
387
388    fn load_executable_accounts(
389        &self,
390        ancestors: &Ancestors,
391        accounts: &mut Vec<(Pubkey, AccountSharedData)>,
392        mut program_account_index: usize,
393        error_counters: &mut ErrorCounters,
394    ) -> Result<Vec<usize>> {
395        let mut account_indices = Vec::new();
396        let mut program_id = accounts[program_account_index].0;
397        let mut depth = 0;
398        while !native_loader::check_id(&program_id) {
399            if depth >= 5 {
400                error_counters.call_chain_too_deep += 1;
401                return Err(TransactionError::CallChainTooDeep);
402            }
403            depth += 1;
404
405            program_account_index = match self
406                .accounts_db
407                .load_with_fixed_root(ancestors, &program_id)
408            {
409                Some((program_account, _)) => {
410                    let account_index = accounts.len();
411                    accounts.push((program_id, program_account));
412                    account_index
413                }
414                None => {
415                    error_counters.account_not_found += 1;
416                    return Err(TransactionError::ProgramAccountNotFound);
417                }
418            };
419            let program = &accounts[program_account_index].1;
420            if !program.executable() {
421                error_counters.invalid_program_for_execution += 1;
422                return Err(TransactionError::InvalidProgramForExecution);
423            }
424
425            // Add loader to chain
426            let program_owner = *program.owner();
427
428            if bpf_loader_upgradeable::check_id(&program_owner) {
429                // The upgradeable loader requires the derived ProgramData account
430                if let Ok(UpgradeableLoaderState::Program {
431                    programdata_address,
432                }) = program.state()
433                {
434                    let programdata_account_index = match self
435                        .accounts_db
436                        .load_with_fixed_root(ancestors, &programdata_address)
437                    {
438                        Some((programdata_account, _)) => {
439                            let account_index = accounts.len();
440                            accounts.push((programdata_address, programdata_account));
441                            account_index
442                        }
443                        None => {
444                            error_counters.account_not_found += 1;
445                            return Err(TransactionError::ProgramAccountNotFound);
446                        }
447                    };
448                    account_indices.insert(0, programdata_account_index);
449                } else {
450                    error_counters.invalid_program_for_execution += 1;
451                    return Err(TransactionError::InvalidProgramForExecution);
452                }
453            }
454
455            account_indices.insert(0, program_account_index);
456            program_id = program_owner;
457        }
458        Ok(account_indices)
459    }
460
461    pub fn load_accounts(
462        &self,
463        ancestors: &Ancestors,
464        txs: &[SanitizedTransaction],
465        lock_results: Vec<TransactionCheckResult>,
466        hash_queue: &BlockhashQueue,
467        error_counters: &mut ErrorCounters,
468        rent_collector: &RentCollector,
469        feature_set: &FeatureSet,
470    ) -> Vec<TransactionLoadResult> {
471        txs.iter()
472            .zip(lock_results)
473            .map(|etx| match etx {
474                (tx, (Ok(()), nonce_rollback)) => {
475                    let fee_calculator = nonce_rollback
476                        .as_ref()
477                        .map(|nonce_rollback| nonce_rollback.fee_calculator())
478                        .unwrap_or_else(|| {
479                            #[allow(deprecated)]
480                            hash_queue
481                                .get_fee_calculator(tx.message().recent_blockhash())
482                                .cloned()
483                        });
484                    let fee = if let Some(fee_calculator) = fee_calculator {
485                        tx.message().calculate_fee(&fee_calculator)
486                    } else {
487                        return (Err(TransactionError::BlockhashNotFound), None);
488                    };
489
490                    let loaded_transaction = match self.load_transaction(
491                        ancestors,
492                        tx,
493                        fee,
494                        error_counters,
495                        rent_collector,
496                        feature_set,
497                    ) {
498                        Ok(loaded_transaction) => loaded_transaction,
499                        Err(e) => return (Err(e), None),
500                    };
501
502                    // Update nonce_rollback with fee-subtracted accounts
503                    let nonce_rollback = if let Some(nonce_rollback) = nonce_rollback {
504                        match NonceRollbackFull::from_partial(
505                            nonce_rollback,
506                            tx.message(),
507                            &loaded_transaction.accounts,
508                        ) {
509                            Ok(nonce_rollback) => Some(nonce_rollback),
510                            Err(e) => return (Err(e), None),
511                        }
512                    } else {
513                        None
514                    };
515
516                    (Ok(loaded_transaction), nonce_rollback)
517                }
518                (_, (Err(e), _nonce_rollback)) => (Err(e), None),
519            })
520            .collect()
521    }
522
523    fn filter_zero_carat_account(
524        account: AccountSharedData,
525        slot: Slot,
526    ) -> Option<(AccountSharedData, Slot)> {
527        if account.carats() > 0 {
528            Some((account, slot))
529        } else {
530            None
531        }
532    }
533
534    /// Slow because lock is held for 1 operation instead of many
535    fn load_slow(
536        &self,
537        ancestors: &Ancestors,
538        pubkey: &Pubkey,
539        load_hint: LoadHint,
540    ) -> Option<(AccountSharedData, Slot)> {
541        let (account, slot) = self.accounts_db.load(ancestors, pubkey, load_hint)?;
542        Self::filter_zero_carat_account(account, slot)
543    }
544
545    pub fn load_with_fixed_root(
546        &self,
547        ancestors: &Ancestors,
548        pubkey: &Pubkey,
549    ) -> Option<(AccountSharedData, Slot)> {
550        self.load_slow(ancestors, pubkey, LoadHint::FixedMaxRoot)
551    }
552
553    pub fn load_without_fixed_root(
554        &self,
555        ancestors: &Ancestors,
556        pubkey: &Pubkey,
557    ) -> Option<(AccountSharedData, Slot)> {
558        self.load_slow(ancestors, pubkey, LoadHint::Unspecified)
559    }
560
561    /// scans underlying accounts_db for this delta (slot) with a map function
562    ///   from LoadedAccount to B
563    /// returns only the latest/current version of B for this slot
564    pub fn scan_slot<F, B>(&self, slot: Slot, func: F) -> Vec<B>
565    where
566        F: Fn(LoadedAccount) -> Option<B> + Send + Sync,
567        B: Sync + Send + Default + std::cmp::Eq,
568    {
569        let scan_result = self.accounts_db.scan_account_storage(
570            slot,
571            |loaded_account: LoadedAccount| {
572                // Cache only has one version per key, don't need to worry about versioning
573                func(loaded_account)
574            },
575            |accum: &DashMap<Pubkey, (u64, B)>, loaded_account: LoadedAccount| {
576                let loaded_account_pubkey = *loaded_account.pubkey();
577                let loaded_write_version = loaded_account.write_version();
578                let should_insert = accum
579                    .get(&loaded_account_pubkey)
580                    .map(|existing_entry| loaded_write_version > existing_entry.value().0)
581                    .unwrap_or(true);
582                if should_insert {
583                    if let Some(val) = func(loaded_account) {
584                        // Detected insertion is necessary, grabs the write lock to commit the write,
585                        match accum.entry(loaded_account_pubkey) {
586                            // Double check in case another thread interleaved a write between the read + write.
587                            Occupied(mut occupied_entry) => {
588                                if loaded_write_version > occupied_entry.get().0 {
589                                    occupied_entry.insert((loaded_write_version, val));
590                                }
591                            }
592
593                            Vacant(vacant_entry) => {
594                                vacant_entry.insert((loaded_write_version, val));
595                            }
596                        }
597                    }
598                }
599            },
600        );
601
602        match scan_result {
603            ScanStorageResult::Cached(cached_result) => cached_result,
604            ScanStorageResult::Stored(stored_result) => stored_result
605                .into_iter()
606                .map(|(_pubkey, (_latest_write_version, val))| val)
607                .collect(),
608        }
609    }
610
611    pub fn load_by_program_slot(
612        &self,
613        slot: Slot,
614        program_id: Option<&Pubkey>,
615    ) -> Vec<(Pubkey, AccountSharedData)> {
616        self.scan_slot(slot, |stored_account| {
617            let hit = match program_id {
618                None => true,
619                Some(program_id) => stored_account.owner() == program_id,
620            };
621
622            if hit {
623                Some((*stored_account.pubkey(), stored_account.take_account()))
624            } else {
625                None
626            }
627        })
628    }
629
630    pub fn load_largest_accounts(
631        &self,
632        ancestors: &Ancestors,
633        bank_id: BankId,
634        num: usize,
635        filter_by_address: &HashSet<Pubkey>,
636        filter: AccountAddressFilter,
637    ) -> ScanResult<Vec<(Pubkey, u64)>> {
638        if num == 0 {
639            return Ok(vec![]);
640        }
641        let account_balances = self.accounts_db.scan_accounts(
642            ancestors,
643            bank_id,
644            |collector: &mut BinaryHeap<Reverse<(u64, Pubkey)>>, option| {
645                if let Some((pubkey, account, _slot)) = option {
646                    if account.carats() == 0 {
647                        return;
648                    }
649                    let contains_address = filter_by_address.contains(pubkey);
650                    let collect = match filter {
651                        AccountAddressFilter::Exclude => !contains_address,
652                        AccountAddressFilter::Include => contains_address,
653                    };
654                    if !collect {
655                        return;
656                    }
657                    if collector.len() == num {
658                        let Reverse(entry) = collector
659                            .peek()
660                            .expect("BinaryHeap::peek should succeed when len > 0");
661                        if *entry >= (account.carats(), *pubkey) {
662                            return;
663                        }
664                        collector.pop();
665                    }
666                    collector.push(Reverse((account.carats(), *pubkey)));
667                }
668            },
669        )?;
670        Ok(account_balances
671            .into_sorted_vec()
672            .into_iter()
673            .map(|Reverse((balance, pubkey))| (pubkey, balance))
674            .collect())
675    }
676
677    pub fn calculate_capitalization(
678        &self,
679        ancestors: &Ancestors,
680        slot: Slot,
681        can_cached_slot_be_unflushed: bool,
682        debug_verify: bool,
683    ) -> u64 {
684        let use_index = false;
685        self.accounts_db
686            .update_accounts_hash_with_index_option(
687                use_index,
688                debug_verify,
689                slot,
690                ancestors,
691                None,
692                can_cached_slot_be_unflushed,
693                None,
694            )
695            .1
696    }
697
698    #[must_use]
699    pub fn verify_bank_hash_and_carats(
700        &self,
701        slot: Slot,
702        ancestors: &Ancestors,
703        total_carats: u64,
704        test_hash_calculation: bool,
705    ) -> bool {
706        if let Err(err) = self.accounts_db.verify_bank_hash_and_carats(
707            slot,
708            ancestors,
709            total_carats,
710            test_hash_calculation,
711        ) {
712            warn!("verify_bank_hash failed: {:?}", err);
713            false
714        } else {
715            true
716        }
717    }
718
719    fn is_loadable(carats: u64) -> bool {
720        // Don't ever load zero carat accounts into runtime because
721        // the existence of zero-carat accounts are never deterministic!!
722        carats > 0
723    }
724
725    fn load_while_filtering<F: Fn(&AccountSharedData) -> bool>(
726        collector: &mut Vec<(Pubkey, AccountSharedData)>,
727        some_account_tuple: Option<(&Pubkey, AccountSharedData, Slot)>,
728        filter: F,
729    ) {
730        if let Some(mapped_account_tuple) = some_account_tuple
731            .filter(|(_, account, _)| Self::is_loadable(account.carats()) && filter(account))
732            .map(|(pubkey, account, _slot)| (*pubkey, account))
733        {
734            collector.push(mapped_account_tuple)
735        }
736    }
737
738    pub fn load_by_program(
739        &self,
740        ancestors: &Ancestors,
741        bank_id: BankId,
742        program_id: &Pubkey,
743    ) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
744        self.accounts_db.scan_accounts(
745            ancestors,
746            bank_id,
747            |collector: &mut Vec<(Pubkey, AccountSharedData)>, some_account_tuple| {
748                Self::load_while_filtering(collector, some_account_tuple, |account| {
749                    account.owner() == program_id
750                })
751            },
752        )
753    }
754
755    pub fn load_by_program_with_filter<F: Fn(&AccountSharedData) -> bool>(
756        &self,
757        ancestors: &Ancestors,
758        bank_id: BankId,
759        program_id: &Pubkey,
760        filter: F,
761    ) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
762        self.accounts_db.scan_accounts(
763            ancestors,
764            bank_id,
765            |collector: &mut Vec<(Pubkey, AccountSharedData)>, some_account_tuple| {
766                Self::load_while_filtering(collector, some_account_tuple, |account| {
767                    account.owner() == program_id && filter(account)
768                })
769            },
770        )
771    }
772
773    pub fn load_by_index_key_with_filter<F: Fn(&AccountSharedData) -> bool>(
774        &self,
775        ancestors: &Ancestors,
776        bank_id: BankId,
777        index_key: &IndexKey,
778        filter: F,
779    ) -> ScanResult<Vec<(Pubkey, AccountSharedData)>> {
780        self.accounts_db
781            .index_scan_accounts(
782                ancestors,
783                bank_id,
784                *index_key,
785                |collector: &mut Vec<(Pubkey, AccountSharedData)>, some_account_tuple| {
786                    Self::load_while_filtering(collector, some_account_tuple, |account| {
787                        filter(account)
788                    })
789                },
790            )
791            .map(|result| result.0)
792    }
793
794    pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
795        self.accounts_db.account_indexes.include_key(key)
796    }
797
798    pub fn load_all(
799        &self,
800        ancestors: &Ancestors,
801        bank_id: BankId,
802    ) -> ScanResult<Vec<(Pubkey, AccountSharedData, Slot)>> {
803        self.accounts_db.scan_accounts(
804            ancestors,
805            bank_id,
806            |collector: &mut Vec<(Pubkey, AccountSharedData, Slot)>, some_account_tuple| {
807                if let Some((pubkey, account, slot)) = some_account_tuple
808                    .filter(|(_, account, _)| Self::is_loadable(account.carats()))
809                {
810                    collector.push((*pubkey, account, slot))
811                }
812            },
813        )
814    }
815
816    pub fn hold_range_in_memory<R>(&self, range: &R, start_holding: bool)
817    where
818        R: RangeBounds<Pubkey> + std::fmt::Debug,
819    {
820        self.accounts_db
821            .accounts_index
822            .hold_range_in_memory(range, start_holding)
823    }
824
825    pub fn load_to_collect_rent_eagerly<R: RangeBounds<Pubkey> + std::fmt::Debug>(
826        &self,
827        ancestors: &Ancestors,
828        range: R,
829    ) -> Vec<(Pubkey, AccountSharedData)> {
830        self.accounts_db.range_scan_accounts(
831            "load_to_collect_rent_eagerly_scan_elapsed",
832            ancestors,
833            range,
834            true,
835            |collector: &mut Vec<(Pubkey, AccountSharedData)>, option| {
836                Self::load_while_filtering(collector, option, |_| true)
837            },
838        )
839    }
840
841    /// Slow because lock is held for 1 operation instead of many.
842    /// WARNING: This noncached version is only to be used for tests/benchmarking
843    /// as bypassing the cache in general is not supported
844    pub fn store_slow_uncached(&self, slot: Slot, pubkey: &Pubkey, account: &AccountSharedData) {
845        self.accounts_db.store_uncached(slot, &[(pubkey, account)]);
846    }
847
848    pub fn store_slow_cached(&self, slot: Slot, pubkey: &Pubkey, account: &AccountSharedData) {
849        self.accounts_db.store_cached(slot, &[(pubkey, account)]);
850    }
851
852    fn lock_account(
853        &self,
854        account_locks: &mut AccountLocks,
855        writable_keys: Vec<&Pubkey>,
856        readonly_keys: Vec<&Pubkey>,
857    ) -> Result<()> {
858        for k in writable_keys.iter() {
859            if account_locks.is_locked_write(k) || account_locks.is_locked_readonly(k) {
860                debug!("Writable account in use: {:?}", k);
861                return Err(TransactionError::AccountInUse);
862            }
863        }
864        for k in readonly_keys.iter() {
865            if account_locks.is_locked_write(k) {
866                debug!("Read-only account in use: {:?}", k);
867                return Err(TransactionError::AccountInUse);
868            }
869        }
870
871        for k in writable_keys {
872            account_locks.write_locks.insert(*k);
873        }
874
875        for k in readonly_keys {
876            if !account_locks.lock_readonly(k) {
877                account_locks.insert_new_readonly(k);
878            }
879        }
880
881        Ok(())
882    }
883
884    fn unlock_account(
885        &self,
886        account_locks: &mut AccountLocks,
887        writable_keys: Vec<&Pubkey>,
888        readonly_keys: Vec<&Pubkey>,
889    ) {
890        for k in writable_keys {
891            account_locks.unlock_write(k);
892        }
893        for k in readonly_keys {
894            account_locks.unlock_readonly(k);
895        }
896    }
897
898    pub fn bank_hash_at(&self, slot: Slot) -> Hash {
899        self.bank_hash_info_at(slot).hash
900    }
901
902    pub fn bank_hash_info_at(&self, slot: Slot) -> BankHashInfo {
903        let delta_hash = self.accounts_db.get_accounts_delta_hash(slot);
904        let bank_hashes = self.accounts_db.bank_hashes.read().unwrap();
905        let mut hash_info = bank_hashes
906            .get(&slot)
907            .expect("No bank hash was found for this bank, that should not be possible")
908            .clone();
909        hash_info.hash = delta_hash;
910        hash_info
911    }
912
913    /// This function will prevent multiple threads from modifying the same account state at the
914    /// same time
915    #[must_use]
916    #[allow(clippy::needless_collect)]
917    pub fn lock_accounts<'a>(
918        &self,
919        txs: impl Iterator<Item = &'a SanitizedTransaction>,
920        demote_program_write_locks: bool,
921    ) -> Vec<Result<()>> {
922        let keys: Vec<_> = txs
923            .map(|tx| tx.get_account_locks(demote_program_write_locks))
924            .collect();
925        let mut account_locks = &mut self.account_locks.lock().unwrap();
926        keys.into_iter()
927            .map(|keys| self.lock_account(&mut account_locks, keys.writable, keys.readonly))
928            .collect()
929    }
930
931    /// Once accounts are unlocked, new transactions that modify that state can enter the pipeline
932    #[allow(clippy::needless_collect)]
933    pub fn unlock_accounts<'a>(
934        &self,
935        txs: impl Iterator<Item = &'a SanitizedTransaction>,
936        results: &[Result<()>],
937        demote_program_write_locks: bool,
938    ) {
939        let keys: Vec<_> = txs
940            .zip(results)
941            .filter_map(|(tx, res)| match res {
942                Err(TransactionError::AccountInUse) => None,
943                Err(TransactionError::SanitizeFailure) => None,
944                Err(TransactionError::AccountLoadedTwice) => None,
945                _ => Some(tx.get_account_locks(demote_program_write_locks)),
946            })
947            .collect();
948        let mut account_locks = self.account_locks.lock().unwrap();
949        debug!("bank unlock accounts");
950        keys.into_iter().for_each(|keys| {
951            self.unlock_account(&mut account_locks, keys.writable, keys.readonly);
952        });
953    }
954
955    /// Store the accounts into the DB
956    // allow(clippy) needed for various gating flags
957    #[allow(clippy::too_many_arguments)]
958    pub fn store_cached<'a>(
959        &self,
960        slot: Slot,
961        txs: &'a [SanitizedTransaction],
962        res: &'a [TransactionExecutionResult],
963        loaded: &'a mut [TransactionLoadResult],
964        rent_collector: &RentCollector,
965        last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
966        rent_for_sysvars: bool,
967        merge_nonce_error_into_system_error: bool,
968        demote_program_write_locks: bool,
969    ) {
970        let accounts_to_store = self.collect_accounts_to_store(
971            txs,
972            res,
973            loaded,
974            rent_collector,
975            last_blockhash_with_fee_calculator,
976            rent_for_sysvars,
977            merge_nonce_error_into_system_error,
978            demote_program_write_locks,
979        );
980        self.accounts_db.store_cached(slot, &accounts_to_store);
981    }
982
983    /// Purge a slot if it is not a root
984    /// Root slots cannot be purged
985    /// `is_from_abs` is true if the caller is the AccountsBackgroundService
986    pub fn purge_slot(&self, slot: Slot, bank_id: BankId, is_from_abs: bool) {
987        self.accounts_db.purge_slot(slot, bank_id, is_from_abs);
988    }
989
990    /// Add a slot to root.  Root slots cannot be purged
991    pub fn add_root(&self, slot: Slot) {
992        self.accounts_db.add_root(slot)
993    }
994
995    fn collect_accounts_to_store<'a>(
996        &self,
997        txs: &'a [SanitizedTransaction],
998        res: &'a [TransactionExecutionResult],
999        loaded: &'a mut [TransactionLoadResult],
1000        rent_collector: &RentCollector,
1001        last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
1002        rent_for_sysvars: bool,
1003        merge_nonce_error_into_system_error: bool,
1004        demote_program_write_locks: bool,
1005    ) -> Vec<(&'a Pubkey, &'a AccountSharedData)> {
1006        let mut accounts = Vec::with_capacity(loaded.len());
1007        for (i, ((raccs, _nonce_rollback), tx)) in loaded.iter_mut().zip(txs).enumerate() {
1008            if raccs.is_err() {
1009                continue;
1010            }
1011            let (res, nonce_rollback) = &res[i];
1012            let maybe_nonce_rollback = match (res, nonce_rollback) {
1013                (Ok(_), Some(nonce_rollback)) => {
1014                    let pubkey = nonce_rollback.nonce_address();
1015                    let acc = nonce_rollback.nonce_account();
1016                    let maybe_fee_account = nonce_rollback.fee_account();
1017                    Some((pubkey, acc, maybe_fee_account, true))
1018                }
1019                (Err(TransactionError::InstructionError(index, _)), Some(nonce_rollback)) => {
1020                    let nonce_marker_ix_failed = if merge_nonce_error_into_system_error {
1021                        // Don't advance stored blockhash when the nonce marker ix fails
1022                        *index == NONCED_TX_MARKER_IX_INDEX
1023                    } else {
1024                        false
1025                    };
1026                    let pubkey = nonce_rollback.nonce_address();
1027                    let acc = nonce_rollback.nonce_account();
1028                    let maybe_fee_account = nonce_rollback.fee_account();
1029                    Some((pubkey, acc, maybe_fee_account, !nonce_marker_ix_failed))
1030                }
1031                (Ok(_), _nonce_rollback) => None,
1032                (Err(_), _nonce_rollback) => continue,
1033            };
1034
1035            let message = tx.message();
1036            let loaded_transaction = raccs.as_mut().unwrap();
1037            let mut fee_payer_index = None;
1038            for (i, (key, account)) in (0..message.account_keys_len())
1039                .zip(loaded_transaction.accounts.iter_mut())
1040                .filter(|(i, _account)| message.is_non_loader_key(*i))
1041            {
1042                let is_nonce_account = prepare_if_nonce_account(
1043                    account,
1044                    key,
1045                    res,
1046                    maybe_nonce_rollback,
1047                    last_blockhash_with_fee_calculator,
1048                );
1049                if fee_payer_index.is_none() {
1050                    fee_payer_index = Some(i);
1051                }
1052                let is_fee_payer = Some(i) == fee_payer_index;
1053                if message.is_writable(i, demote_program_write_locks)
1054                    && (res.is_ok()
1055                        || (maybe_nonce_rollback.is_some() && (is_nonce_account || is_fee_payer)))
1056                {
1057                    if res.is_err() {
1058                        match (is_nonce_account, is_fee_payer, maybe_nonce_rollback) {
1059                            // nonce is fee-payer, state updated in `prepare_if_nonce_account()`
1060                            (true, true, Some((_, _, None, _))) => (),
1061                            // nonce not fee-payer, state updated in `prepare_if_nonce_account()`
1062                            (true, false, Some((_, _, Some(_), _))) => (),
1063                            // not nonce, but fee-payer. rollback to cached state
1064                            (false, true, Some((_, _, Some(fee_payer_account), _))) => {
1065                                *account = fee_payer_account.clone();
1066                            }
1067                            _ => panic!("unexpected nonce_rollback condition"),
1068                        }
1069                    }
1070                    if account.rent_epoch() == INITIAL_RENT_EPOCH {
1071                        let rent = rent_collector.collect_from_created_account(
1072                            key,
1073                            account,
1074                            rent_for_sysvars,
1075                        );
1076                        loaded_transaction.rent += rent;
1077                        loaded_transaction
1078                            .rent_debits
1079                            .push(key, rent, account.carats());
1080                    }
1081                    accounts.push((&*key, &*account));
1082                }
1083            }
1084        }
1085        accounts
1086    }
1087}
1088
1089pub fn prepare_if_nonce_account(
1090    account: &mut AccountSharedData,
1091    account_pubkey: &Pubkey,
1092    tx_result: &Result<()>,
1093    maybe_nonce_rollback: Option<(
1094        &Pubkey,
1095        &AccountSharedData,
1096        Option<&AccountSharedData>,
1097        bool,
1098    )>,
1099    last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
1100) -> bool {
1101    if let Some((nonce_key, nonce_acc, _maybe_fee_account, advance_blockhash)) =
1102        maybe_nonce_rollback
1103    {
1104        if account_pubkey == nonce_key {
1105            if tx_result.is_err() {
1106                // Nonce TX failed with an InstructionError. Roll back
1107                // its account state
1108                *account = nonce_acc.clone();
1109            }
1110
1111            if advance_blockhash {
1112                // Advance the stored blockhash to prevent fee theft by replaying
1113                // transactions that have failed with an `InstructionError`
1114
1115                // Since hash_age_kind is DurableNonce, unwrap is safe here
1116                let state = StateMut::<nonce::state::Versions>::state(nonce_acc)
1117                    .unwrap()
1118                    .convert_to_current();
1119                if let nonce::State::Initialized(ref data) = state {
1120                    let new_data = nonce::state::Versions::new_current(nonce::State::Initialized(
1121                        nonce::state::Data {
1122                            blockhash: last_blockhash_with_fee_calculator.0,
1123                            fee_calculator: last_blockhash_with_fee_calculator.1.clone(),
1124                            ..data.clone()
1125                        },
1126                    ));
1127                    account.set_state(&new_data).unwrap();
1128                }
1129            }
1130            return true;
1131        }
1132    }
1133    false
1134}
1135
1136fn is_upgradeable_loader_present(message: &SanitizedMessage) -> bool {
1137    message
1138        .account_keys_iter()
1139        .any(|&key| key == bpf_loader_upgradeable::id())
1140}
1141
1142pub fn create_test_accounts(
1143    accounts: &Accounts,
1144    pubkeys: &mut Vec<Pubkey>,
1145    num: usize,
1146    slot: Slot,
1147) {
1148    for t in 0..num {
1149        let pubkey = gemachain_sdk::pubkey::new_rand();
1150        let account =
1151            AccountSharedData::new((t + 1) as u64, 0, AccountSharedData::default().owner());
1152        accounts.store_slow_uncached(slot, &pubkey, &account);
1153        pubkeys.push(pubkey);
1154    }
1155}
1156
1157// Only used by bench, not safe to call otherwise accounts can conflict with the
1158// accounts cache!
1159pub fn update_accounts_bench(accounts: &Accounts, pubkeys: &[Pubkey], slot: u64) {
1160    for pubkey in pubkeys {
1161        let amount = thread_rng().gen_range(0, 10);
1162        let account = AccountSharedData::new(amount, 0, AccountSharedData::default().owner());
1163        accounts.store_slow_uncached(slot, pubkey, &account);
1164    }
1165}
1166
1167#[cfg(test)]
1168mod tests {
1169    use super::*;
1170    use crate::rent_collector::RentCollector;
1171    use gemachain_sdk::{
1172        account::{AccountSharedData, WritableAccount},
1173        epoch_schedule::EpochSchedule,
1174        fee_calculator::FeeCalculator,
1175        genesis_config::ClusterType,
1176        hash::Hash,
1177        instruction::{CompiledInstruction, InstructionError},
1178        message::Message,
1179        nonce, nonce_account,
1180        rent::Rent,
1181        signature::{keypair_from_seed, signers::Signers, Keypair, Signer},
1182        system_instruction, system_program,
1183        transaction::Transaction,
1184    };
1185    use std::{
1186        convert::TryFrom,
1187        sync::atomic::{AtomicBool, AtomicU64, Ordering},
1188        {thread, time},
1189    };
1190
1191    fn new_sanitized_tx<T: Signers>(
1192        from_keypairs: &T,
1193        message: Message,
1194        recent_blockhash: Hash,
1195    ) -> SanitizedTransaction {
1196        SanitizedTransaction::try_from(Transaction::new(from_keypairs, message, recent_blockhash))
1197            .unwrap()
1198    }
1199
1200    fn load_accounts_with_fee_and_rent(
1201        tx: Transaction,
1202        ka: &[(Pubkey, AccountSharedData)],
1203        fee_calculator: &FeeCalculator,
1204        rent_collector: &RentCollector,
1205        error_counters: &mut ErrorCounters,
1206    ) -> Vec<TransactionLoadResult> {
1207        let mut hash_queue = BlockhashQueue::new(100);
1208        hash_queue.register_hash(&tx.message().recent_blockhash, fee_calculator);
1209        let accounts = Accounts::new_with_config_for_tests(
1210            Vec::new(),
1211            &ClusterType::Development,
1212            AccountSecondaryIndexes::default(),
1213            false,
1214            AccountShrinkThreshold::default(),
1215        );
1216        for ka in ka.iter() {
1217            accounts.store_slow_uncached(0, &ka.0, &ka.1);
1218        }
1219
1220        let ancestors = vec![(0, 0)].into_iter().collect();
1221        let sanitized_tx = SanitizedTransaction::try_from(tx).unwrap();
1222        accounts.load_accounts(
1223            &ancestors,
1224            &[sanitized_tx],
1225            vec![(Ok(()), None)],
1226            &hash_queue,
1227            error_counters,
1228            rent_collector,
1229            &FeatureSet::all_enabled(),
1230        )
1231    }
1232
1233    fn load_accounts_with_fee(
1234        tx: Transaction,
1235        ka: &[(Pubkey, AccountSharedData)],
1236        fee_calculator: &FeeCalculator,
1237        error_counters: &mut ErrorCounters,
1238    ) -> Vec<TransactionLoadResult> {
1239        let rent_collector = RentCollector::default();
1240        load_accounts_with_fee_and_rent(tx, ka, fee_calculator, &rent_collector, error_counters)
1241    }
1242
1243    fn load_accounts(
1244        tx: Transaction,
1245        ka: &[(Pubkey, AccountSharedData)],
1246        error_counters: &mut ErrorCounters,
1247    ) -> Vec<TransactionLoadResult> {
1248        let fee_calculator = FeeCalculator::default();
1249        load_accounts_with_fee(tx, ka, &fee_calculator, error_counters)
1250    }
1251
1252    #[test]
1253    fn test_hold_range_in_memory() {
1254        let accts = Accounts::default_for_tests();
1255        let range = Pubkey::new(&[0; 32])..=Pubkey::new(&[0xff; 32]);
1256        accts.hold_range_in_memory(&range, true);
1257        accts.hold_range_in_memory(&range, false);
1258        accts.hold_range_in_memory(&range, true);
1259        accts.hold_range_in_memory(&range, true);
1260        accts.hold_range_in_memory(&range, false);
1261        accts.hold_range_in_memory(&range, false);
1262    }
1263
1264    #[test]
1265    fn test_hold_range_in_memory2() {
1266        let accts = Accounts::default_for_tests();
1267        let range = Pubkey::new(&[0; 32])..=Pubkey::new(&[0xff; 32]);
1268        let idx = &accts.accounts_db.accounts_index;
1269        let bins = idx.account_maps.len();
1270        // use bins * 2 to get the first half of the range within bin 0
1271        let bins_2 = bins * 2;
1272        let binner = crate::pubkey_bins::PubkeyBinCalculator16::new(bins_2);
1273        let range2 =
1274            binner.lowest_pubkey_from_bin(0, bins_2)..binner.lowest_pubkey_from_bin(1, bins_2);
1275        let range2_inclusive = range2.start..=range2.end;
1276        assert_eq!(0, idx.bin_calculator.bin_from_pubkey(&range2.start));
1277        assert_eq!(0, idx.bin_calculator.bin_from_pubkey(&range2.end));
1278        accts.hold_range_in_memory(&range, true);
1279        idx.account_maps.iter().enumerate().for_each(|(_bin, map)| {
1280            let map = map.read().unwrap();
1281            assert_eq!(
1282                map.cache_ranges_held.read().unwrap().to_vec(),
1283                vec![Some(range.clone())]
1284            );
1285        });
1286        accts.hold_range_in_memory(&range2, true);
1287        idx.account_maps.iter().enumerate().for_each(|(bin, map)| {
1288            let map = map.read().unwrap();
1289            let expected = if bin == 0 {
1290                vec![Some(range.clone()), Some(range2_inclusive.clone())]
1291            } else {
1292                vec![Some(range.clone())]
1293            };
1294            assert_eq!(
1295                map.cache_ranges_held.read().unwrap().to_vec(),
1296                expected,
1297                "bin: {}",
1298                bin
1299            );
1300        });
1301        accts.hold_range_in_memory(&range, false);
1302        accts.hold_range_in_memory(&range2, false);
1303    }
1304
1305    #[test]
1306    fn test_load_accounts_no_account_0_exists() {
1307        let accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1308        let mut error_counters = ErrorCounters::default();
1309
1310        let keypair = Keypair::new();
1311
1312        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1313        let tx = Transaction::new_with_compiled_instructions(
1314            &[&keypair],
1315            &[],
1316            Hash::default(),
1317            vec![native_loader::id()],
1318            instructions,
1319        );
1320
1321        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1322
1323        assert_eq!(error_counters.account_not_found, 1);
1324        assert_eq!(loaded_accounts.len(), 1);
1325        assert_eq!(
1326            loaded_accounts[0],
1327            (Err(TransactionError::AccountNotFound), None,),
1328        );
1329    }
1330
1331    #[test]
1332    fn test_load_accounts_unknown_program_id() {
1333        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1334        let mut error_counters = ErrorCounters::default();
1335
1336        let keypair = Keypair::new();
1337        let key0 = keypair.pubkey();
1338        let key1 = Pubkey::new(&[5u8; 32]);
1339
1340        let account = AccountSharedData::new(1, 0, &Pubkey::default());
1341        accounts.push((key0, account));
1342
1343        let account = AccountSharedData::new(2, 1, &Pubkey::default());
1344        accounts.push((key1, account));
1345
1346        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1347        let tx = Transaction::new_with_compiled_instructions(
1348            &[&keypair],
1349            &[],
1350            Hash::default(),
1351            vec![Pubkey::default()],
1352            instructions,
1353        );
1354
1355        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1356
1357        assert_eq!(error_counters.account_not_found, 1);
1358        assert_eq!(loaded_accounts.len(), 1);
1359        assert_eq!(
1360            loaded_accounts[0],
1361            (Err(TransactionError::ProgramAccountNotFound), None,)
1362        );
1363    }
1364
1365    #[test]
1366    fn test_load_accounts_insufficient_funds() {
1367        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1368        let mut error_counters = ErrorCounters::default();
1369
1370        let keypair = Keypair::new();
1371        let key0 = keypair.pubkey();
1372
1373        let account = AccountSharedData::new(1, 0, &Pubkey::default());
1374        accounts.push((key0, account));
1375
1376        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1377        let tx = Transaction::new_with_compiled_instructions(
1378            &[&keypair],
1379            &[],
1380            Hash::default(),
1381            vec![native_loader::id()],
1382            instructions,
1383        );
1384
1385        let fee_calculator = FeeCalculator::new(10);
1386        #[allow(deprecated)]
1387        let fee = fee_calculator.calculate_fee(tx.message());
1388        assert_eq!(fee, 10);
1389
1390        let loaded_accounts =
1391            load_accounts_with_fee(tx, &accounts, &fee_calculator, &mut error_counters);
1392
1393        assert_eq!(error_counters.insufficient_funds, 1);
1394        assert_eq!(loaded_accounts.len(), 1);
1395        assert_eq!(
1396            loaded_accounts[0].clone(),
1397            (Err(TransactionError::InsufficientFundsForFee), None,),
1398        );
1399    }
1400
1401    #[test]
1402    fn test_load_accounts_invalid_account_for_fee() {
1403        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1404        let mut error_counters = ErrorCounters::default();
1405
1406        let keypair = Keypair::new();
1407        let key0 = keypair.pubkey();
1408
1409        let account = AccountSharedData::new(1, 1, &gemachain_sdk::pubkey::new_rand()); // <-- owner is not the system program
1410        accounts.push((key0, account));
1411
1412        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1413        let tx = Transaction::new_with_compiled_instructions(
1414            &[&keypair],
1415            &[],
1416            Hash::default(),
1417            vec![native_loader::id()],
1418            instructions,
1419        );
1420
1421        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1422
1423        assert_eq!(error_counters.invalid_account_for_fee, 1);
1424        assert_eq!(loaded_accounts.len(), 1);
1425        assert_eq!(
1426            loaded_accounts[0],
1427            (Err(TransactionError::InvalidAccountForFee), None,),
1428        );
1429    }
1430
1431    #[test]
1432    fn test_load_accounts_fee_payer_is_nonce() {
1433        let mut error_counters = ErrorCounters::default();
1434        let rent_collector = RentCollector::new(
1435            0,
1436            &EpochSchedule::default(),
1437            500_000.0,
1438            &Rent {
1439                carats_per_byte_year: 42,
1440                ..Rent::default()
1441            },
1442        );
1443        let min_balance = rent_collector.rent.minimum_balance(nonce::State::size());
1444        let fee_calculator = FeeCalculator::new(min_balance);
1445        let nonce = Keypair::new();
1446        let mut accounts = vec![(
1447            nonce.pubkey(),
1448            AccountSharedData::new_data(
1449                min_balance * 2,
1450                &nonce::state::Versions::new_current(nonce::State::Initialized(
1451                    nonce::state::Data::default(),
1452                )),
1453                &system_program::id(),
1454            )
1455            .unwrap(),
1456        )];
1457        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1458        let tx = Transaction::new_with_compiled_instructions(
1459            &[&nonce],
1460            &[],
1461            Hash::default(),
1462            vec![native_loader::id()],
1463            instructions,
1464        );
1465
1466        // Fee leaves min_balance balance succeeds
1467        let loaded_accounts = load_accounts_with_fee_and_rent(
1468            tx.clone(),
1469            &accounts,
1470            &fee_calculator,
1471            &rent_collector,
1472            &mut error_counters,
1473        );
1474        assert_eq!(loaded_accounts.len(), 1);
1475        let (load_res, _nonce_rollback) = &loaded_accounts[0];
1476        let loaded_transaction = load_res.as_ref().unwrap();
1477        assert_eq!(loaded_transaction.accounts[0].1.carats(), min_balance);
1478
1479        // Fee leaves zero balance fails
1480        accounts[0].1.set_carats(min_balance);
1481        let loaded_accounts = load_accounts_with_fee_and_rent(
1482            tx.clone(),
1483            &accounts,
1484            &fee_calculator,
1485            &rent_collector,
1486            &mut error_counters,
1487        );
1488        assert_eq!(loaded_accounts.len(), 1);
1489        let (load_res, _nonce_rollback) = &loaded_accounts[0];
1490        assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
1491
1492        // Fee leaves non-zero, but sub-min_balance balance fails
1493        accounts[0].1.set_carats(3 * min_balance / 2);
1494        let loaded_accounts = load_accounts_with_fee_and_rent(
1495            tx,
1496            &accounts,
1497            &fee_calculator,
1498            &rent_collector,
1499            &mut error_counters,
1500        );
1501        assert_eq!(loaded_accounts.len(), 1);
1502        let (load_res, _nonce_rollback) = &loaded_accounts[0];
1503        assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
1504    }
1505
1506    #[test]
1507    fn test_load_accounts_no_loaders() {
1508        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1509        let mut error_counters = ErrorCounters::default();
1510
1511        let keypair = Keypair::new();
1512        let key0 = keypair.pubkey();
1513        let key1 = Pubkey::new(&[5u8; 32]);
1514
1515        let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1516        account.set_rent_epoch(1);
1517        accounts.push((key0, account));
1518
1519        let mut account = AccountSharedData::new(2, 1, &Pubkey::default());
1520        account.set_rent_epoch(1);
1521        accounts.push((key1, account));
1522
1523        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
1524        let tx = Transaction::new_with_compiled_instructions(
1525            &[&keypair],
1526            &[key1],
1527            Hash::default(),
1528            vec![native_loader::id()],
1529            instructions,
1530        );
1531
1532        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1533
1534        assert_eq!(error_counters.account_not_found, 0);
1535        assert_eq!(loaded_accounts.len(), 1);
1536        match &loaded_accounts[0] {
1537            (Ok(loaded_transaction), _nonce_rollback) => {
1538                assert_eq!(loaded_transaction.accounts.len(), 3);
1539                assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
1540                assert_eq!(loaded_transaction.program_indices.len(), 1);
1541                assert_eq!(loaded_transaction.program_indices[0].len(), 0);
1542            }
1543            (Err(e), _nonce_rollback) => Err(e).unwrap(),
1544        }
1545    }
1546
1547    #[test]
1548    fn test_load_accounts_max_call_depth() {
1549        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1550        let mut error_counters = ErrorCounters::default();
1551
1552        let keypair = Keypair::new();
1553        let key0 = keypair.pubkey();
1554        let key1 = Pubkey::new(&[5u8; 32]);
1555        let key2 = Pubkey::new(&[6u8; 32]);
1556        let key3 = Pubkey::new(&[7u8; 32]);
1557        let key4 = Pubkey::new(&[8u8; 32]);
1558        let key5 = Pubkey::new(&[9u8; 32]);
1559        let key6 = Pubkey::new(&[10u8; 32]);
1560
1561        let account = AccountSharedData::new(1, 0, &Pubkey::default());
1562        accounts.push((key0, account));
1563
1564        let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
1565        account.set_executable(true);
1566        account.set_owner(native_loader::id());
1567        accounts.push((key1, account));
1568
1569        let mut account = AccountSharedData::new(41, 1, &Pubkey::default());
1570        account.set_executable(true);
1571        account.set_owner(key1);
1572        accounts.push((key2, account));
1573
1574        let mut account = AccountSharedData::new(42, 1, &Pubkey::default());
1575        account.set_executable(true);
1576        account.set_owner(key2);
1577        accounts.push((key3, account));
1578
1579        let mut account = AccountSharedData::new(43, 1, &Pubkey::default());
1580        account.set_executable(true);
1581        account.set_owner(key3);
1582        accounts.push((key4, account));
1583
1584        let mut account = AccountSharedData::new(44, 1, &Pubkey::default());
1585        account.set_executable(true);
1586        account.set_owner(key4);
1587        accounts.push((key5, account));
1588
1589        let mut account = AccountSharedData::new(45, 1, &Pubkey::default());
1590        account.set_executable(true);
1591        account.set_owner(key5);
1592        accounts.push((key6, account));
1593
1594        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1595        let tx = Transaction::new_with_compiled_instructions(
1596            &[&keypair],
1597            &[],
1598            Hash::default(),
1599            vec![key6],
1600            instructions,
1601        );
1602
1603        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1604
1605        assert_eq!(error_counters.call_chain_too_deep, 1);
1606        assert_eq!(loaded_accounts.len(), 1);
1607        assert_eq!(
1608            loaded_accounts[0],
1609            (Err(TransactionError::CallChainTooDeep), None,)
1610        );
1611    }
1612
1613    #[test]
1614    fn test_load_accounts_bad_owner() {
1615        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1616        let mut error_counters = ErrorCounters::default();
1617
1618        let keypair = Keypair::new();
1619        let key0 = keypair.pubkey();
1620        let key1 = Pubkey::new(&[5u8; 32]);
1621
1622        let account = AccountSharedData::new(1, 0, &Pubkey::default());
1623        accounts.push((key0, account));
1624
1625        let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
1626        account.set_executable(true);
1627        accounts.push((key1, account));
1628
1629        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1630        let tx = Transaction::new_with_compiled_instructions(
1631            &[&keypair],
1632            &[],
1633            Hash::default(),
1634            vec![key1],
1635            instructions,
1636        );
1637
1638        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1639
1640        assert_eq!(error_counters.account_not_found, 1);
1641        assert_eq!(loaded_accounts.len(), 1);
1642        assert_eq!(
1643            loaded_accounts[0],
1644            (Err(TransactionError::ProgramAccountNotFound), None,)
1645        );
1646    }
1647
1648    #[test]
1649    fn test_load_accounts_not_executable() {
1650        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1651        let mut error_counters = ErrorCounters::default();
1652
1653        let keypair = Keypair::new();
1654        let key0 = keypair.pubkey();
1655        let key1 = Pubkey::new(&[5u8; 32]);
1656
1657        let account = AccountSharedData::new(1, 0, &Pubkey::default());
1658        accounts.push((key0, account));
1659
1660        let account = AccountSharedData::new(40, 1, &native_loader::id());
1661        accounts.push((key1, account));
1662
1663        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1664        let tx = Transaction::new_with_compiled_instructions(
1665            &[&keypair],
1666            &[],
1667            Hash::default(),
1668            vec![key1],
1669            instructions,
1670        );
1671
1672        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1673
1674        assert_eq!(error_counters.invalid_program_for_execution, 1);
1675        assert_eq!(loaded_accounts.len(), 1);
1676        assert_eq!(
1677            loaded_accounts[0],
1678            (Err(TransactionError::InvalidProgramForExecution), None,)
1679        );
1680    }
1681
1682    #[test]
1683    fn test_load_accounts_multiple_loaders() {
1684        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1685        let mut error_counters = ErrorCounters::default();
1686
1687        let keypair = Keypair::new();
1688        let key0 = keypair.pubkey();
1689        let key1 = Pubkey::new(&[5u8; 32]);
1690        let key2 = Pubkey::new(&[6u8; 32]);
1691
1692        let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1693        account.set_rent_epoch(1);
1694        accounts.push((key0, account));
1695
1696        let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
1697        account.set_executable(true);
1698        account.set_rent_epoch(1);
1699        account.set_owner(native_loader::id());
1700        accounts.push((key1, account));
1701
1702        let mut account = AccountSharedData::new(41, 1, &Pubkey::default());
1703        account.set_executable(true);
1704        account.set_rent_epoch(1);
1705        account.set_owner(key1);
1706        accounts.push((key2, account));
1707
1708        let instructions = vec![
1709            CompiledInstruction::new(1, &(), vec![0]),
1710            CompiledInstruction::new(2, &(), vec![0]),
1711        ];
1712        let tx = Transaction::new_with_compiled_instructions(
1713            &[&keypair],
1714            &[],
1715            Hash::default(),
1716            vec![key1, key2],
1717            instructions,
1718        );
1719
1720        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1721
1722        assert_eq!(error_counters.account_not_found, 0);
1723        assert_eq!(loaded_accounts.len(), 1);
1724        match &loaded_accounts[0] {
1725            (Ok(loaded_transaction), _nonce_rollback) => {
1726                assert_eq!(loaded_transaction.accounts.len(), 6);
1727                assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
1728                assert_eq!(loaded_transaction.program_indices.len(), 2);
1729                assert_eq!(loaded_transaction.program_indices[0].len(), 1);
1730                assert_eq!(loaded_transaction.program_indices[1].len(), 2);
1731                for program_indices in loaded_transaction.program_indices.iter() {
1732                    for (i, program_index) in program_indices.iter().enumerate() {
1733                        // +1 to skip first not loader account
1734                        assert_eq!(
1735                            loaded_transaction.accounts[*program_index].0,
1736                            accounts[i + 1].0
1737                        );
1738                        assert_eq!(
1739                            loaded_transaction.accounts[*program_index].1,
1740                            accounts[i + 1].1
1741                        );
1742                    }
1743                }
1744            }
1745            (Err(e), _nonce_rollback) => Err(e).unwrap(),
1746        }
1747    }
1748
1749    #[test]
1750    fn test_load_by_program_slot() {
1751        let accounts = Accounts::new_with_config_for_tests(
1752            Vec::new(),
1753            &ClusterType::Development,
1754            AccountSecondaryIndexes::default(),
1755            false,
1756            AccountShrinkThreshold::default(),
1757        );
1758
1759        // Load accounts owned by various programs into AccountsDb
1760        let pubkey0 = gemachain_sdk::pubkey::new_rand();
1761        let account0 = AccountSharedData::new(1, 0, &Pubkey::new(&[2; 32]));
1762        accounts.store_slow_uncached(0, &pubkey0, &account0);
1763        let pubkey1 = gemachain_sdk::pubkey::new_rand();
1764        let account1 = AccountSharedData::new(1, 0, &Pubkey::new(&[2; 32]));
1765        accounts.store_slow_uncached(0, &pubkey1, &account1);
1766        let pubkey2 = gemachain_sdk::pubkey::new_rand();
1767        let account2 = AccountSharedData::new(1, 0, &Pubkey::new(&[3; 32]));
1768        accounts.store_slow_uncached(0, &pubkey2, &account2);
1769
1770        let loaded = accounts.load_by_program_slot(0, Some(&Pubkey::new(&[2; 32])));
1771        assert_eq!(loaded.len(), 2);
1772        let loaded = accounts.load_by_program_slot(0, Some(&Pubkey::new(&[3; 32])));
1773        assert_eq!(loaded, vec![(pubkey2, account2)]);
1774        let loaded = accounts.load_by_program_slot(0, Some(&Pubkey::new(&[4; 32])));
1775        assert_eq!(loaded, vec![]);
1776    }
1777
1778    #[test]
1779    fn test_load_accounts_executable_with_write_lock() {
1780        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1781        let mut error_counters = ErrorCounters::default();
1782
1783        let keypair = Keypair::new();
1784        let key0 = keypair.pubkey();
1785        let key1 = Pubkey::new(&[5u8; 32]);
1786        let key2 = Pubkey::new(&[6u8; 32]);
1787
1788        let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1789        account.set_rent_epoch(1);
1790        accounts.push((key0, account));
1791
1792        let mut account = AccountSharedData::new(40, 1, &native_loader::id());
1793        account.set_executable(true);
1794        account.set_rent_epoch(1);
1795        accounts.push((key1, account));
1796
1797        let mut account = AccountSharedData::new(40, 1, &native_loader::id());
1798        account.set_executable(true);
1799        account.set_rent_epoch(1);
1800        accounts.push((key2, account));
1801
1802        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
1803        let mut message = Message::new_with_compiled_instructions(
1804            1,
1805            0,
1806            1, // only one executable marked as readonly
1807            vec![key0, key1, key2],
1808            Hash::default(),
1809            instructions,
1810        );
1811        let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1812        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1813
1814        assert_eq!(error_counters.invalid_writable_account, 1);
1815        assert_eq!(loaded_accounts.len(), 1);
1816        assert_eq!(
1817            loaded_accounts[0],
1818            (Err(TransactionError::InvalidWritableAccount), None)
1819        );
1820
1821        // Mark executables as readonly
1822        message.account_keys = vec![key0, key1, key2]; // revert key change
1823        message.header.num_readonly_unsigned_accounts = 2; // mark both executables as readonly
1824        let tx = Transaction::new(&[&keypair], message, Hash::default());
1825        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1826
1827        assert_eq!(error_counters.invalid_writable_account, 1);
1828        assert_eq!(loaded_accounts.len(), 1);
1829        let result = loaded_accounts[0].0.as_ref().unwrap();
1830        assert_eq!(result.accounts[..2], accounts[..2]);
1831        assert_eq!(result.accounts[result.program_indices[0][0]], accounts[2]);
1832    }
1833
1834    #[test]
1835    fn test_load_accounts_upgradeable_with_write_lock() {
1836        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1837        let mut error_counters = ErrorCounters::default();
1838
1839        let keypair = Keypair::new();
1840        let key0 = keypair.pubkey();
1841        let key1 = Pubkey::new(&[5u8; 32]);
1842        let key2 = Pubkey::new(&[6u8; 32]);
1843        let programdata_key1 = Pubkey::new(&[7u8; 32]);
1844        let programdata_key2 = Pubkey::new(&[8u8; 32]);
1845
1846        let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1847        account.set_rent_epoch(1);
1848        accounts.push((key0, account));
1849
1850        let program_data = UpgradeableLoaderState::ProgramData {
1851            slot: 42,
1852            upgrade_authority_address: None,
1853        };
1854
1855        let program = UpgradeableLoaderState::Program {
1856            programdata_address: programdata_key1,
1857        };
1858        let mut account =
1859            AccountSharedData::new_data(40, &program, &bpf_loader_upgradeable::id()).unwrap();
1860        account.set_executable(true);
1861        account.set_rent_epoch(1);
1862        accounts.push((key1, account));
1863        let mut account =
1864            AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap();
1865        account.set_rent_epoch(1);
1866        accounts.push((programdata_key1, account));
1867
1868        let program = UpgradeableLoaderState::Program {
1869            programdata_address: programdata_key2,
1870        };
1871        let mut account =
1872            AccountSharedData::new_data(40, &program, &bpf_loader_upgradeable::id()).unwrap();
1873        account.set_executable(true);
1874        account.set_rent_epoch(1);
1875        accounts.push((key2, account));
1876        let mut account =
1877            AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap();
1878        account.set_rent_epoch(1);
1879        accounts.push((programdata_key2, account));
1880
1881        let mut account = AccountSharedData::new(40, 1, &native_loader::id()); // create mock bpf_loader_upgradeable
1882        account.set_executable(true);
1883        account.set_rent_epoch(1);
1884        accounts.push((bpf_loader_upgradeable::id(), account));
1885
1886        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
1887        let mut message = Message::new_with_compiled_instructions(
1888            1,
1889            0,
1890            1, // only one executable marked as readonly
1891            vec![key0, key1, key2],
1892            Hash::default(),
1893            instructions,
1894        );
1895        let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1896        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1897
1898        assert_eq!(error_counters.invalid_writable_account, 1);
1899        assert_eq!(loaded_accounts.len(), 1);
1900        assert_eq!(
1901            loaded_accounts[0],
1902            (Err(TransactionError::InvalidWritableAccount), None)
1903        );
1904
1905        // Solution 1: include bpf_loader_upgradeable account
1906        message.account_keys = vec![key0, key1, bpf_loader_upgradeable::id()];
1907        let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1908        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1909
1910        assert_eq!(error_counters.invalid_writable_account, 1);
1911        assert_eq!(loaded_accounts.len(), 1);
1912        let result = loaded_accounts[0].0.as_ref().unwrap();
1913        assert_eq!(result.accounts[..2], accounts[..2]);
1914        assert_eq!(result.accounts[result.program_indices[0][0]], accounts[5]);
1915
1916        // Solution 2: mark programdata as readonly
1917        message.account_keys = vec![key0, key1, key2]; // revert key change
1918        message.header.num_readonly_unsigned_accounts = 2; // mark both executables as readonly
1919        let tx = Transaction::new(&[&keypair], message, Hash::default());
1920        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1921
1922        assert_eq!(error_counters.invalid_writable_account, 1);
1923        assert_eq!(loaded_accounts.len(), 1);
1924        let result = loaded_accounts[0].0.as_ref().unwrap();
1925        assert_eq!(result.accounts[..2], accounts[..2]);
1926        assert_eq!(result.accounts[result.program_indices[0][0]], accounts[5]);
1927        assert_eq!(result.accounts[result.program_indices[0][1]], accounts[3]);
1928        assert_eq!(result.accounts[result.program_indices[0][2]], accounts[4]);
1929    }
1930
1931    #[test]
1932    fn test_load_accounts_programdata_with_write_lock() {
1933        let mut accounts: Vec<(Pubkey, AccountSharedData)> = Vec::new();
1934        let mut error_counters = ErrorCounters::default();
1935
1936        let keypair = Keypair::new();
1937        let key0 = keypair.pubkey();
1938        let key1 = Pubkey::new(&[5u8; 32]);
1939        let key2 = Pubkey::new(&[6u8; 32]);
1940
1941        let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1942        account.set_rent_epoch(1);
1943        accounts.push((key0, account));
1944
1945        let program_data = UpgradeableLoaderState::ProgramData {
1946            slot: 42,
1947            upgrade_authority_address: None,
1948        };
1949        let mut account =
1950            AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap();
1951        account.set_rent_epoch(1);
1952        accounts.push((key1, account));
1953
1954        let mut account = AccountSharedData::new(40, 1, &native_loader::id());
1955        account.set_executable(true);
1956        account.set_rent_epoch(1);
1957        accounts.push((key2, account));
1958
1959        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
1960        let mut message = Message::new_with_compiled_instructions(
1961            1,
1962            0,
1963            1, // only the program marked as readonly
1964            vec![key0, key1, key2],
1965            Hash::default(),
1966            instructions,
1967        );
1968        let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1969        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1970
1971        assert_eq!(error_counters.invalid_writable_account, 1);
1972        assert_eq!(loaded_accounts.len(), 1);
1973        assert_eq!(
1974            loaded_accounts[0],
1975            (Err(TransactionError::InvalidWritableAccount), None)
1976        );
1977
1978        // Solution 1: include bpf_loader_upgradeable account
1979        let mut account = AccountSharedData::new(40, 1, &native_loader::id()); // create mock bpf_loader_upgradeable
1980        account.set_executable(true);
1981        account.set_rent_epoch(1);
1982        let accounts_with_upgradeable_loader = vec![
1983            accounts[0].clone(),
1984            accounts[1].clone(),
1985            (bpf_loader_upgradeable::id(), account),
1986        ];
1987        message.account_keys = vec![key0, key1, bpf_loader_upgradeable::id()];
1988        let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
1989        let loaded_accounts =
1990            load_accounts(tx, &accounts_with_upgradeable_loader, &mut error_counters);
1991
1992        assert_eq!(error_counters.invalid_writable_account, 1);
1993        assert_eq!(loaded_accounts.len(), 1);
1994        let result = loaded_accounts[0].0.as_ref().unwrap();
1995        assert_eq!(result.accounts[..2], accounts_with_upgradeable_loader[..2]);
1996        assert_eq!(
1997            result.accounts[result.program_indices[0][0]],
1998            accounts_with_upgradeable_loader[2]
1999        );
2000
2001        // Solution 2: mark programdata as readonly
2002        message.account_keys = vec![key0, key1, key2]; // revert key change
2003        message.header.num_readonly_unsigned_accounts = 2; // extend readonly set to include programdata
2004        let tx = Transaction::new(&[&keypair], message, Hash::default());
2005        let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2006
2007        assert_eq!(error_counters.invalid_writable_account, 1);
2008        assert_eq!(loaded_accounts.len(), 1);
2009        let result = loaded_accounts[0].0.as_ref().unwrap();
2010        assert_eq!(result.accounts[..2], accounts[..2]);
2011        assert_eq!(result.accounts[result.program_indices[0][0]], accounts[2]);
2012    }
2013
2014    #[test]
2015    fn test_accounts_account_not_found() {
2016        let accounts = Accounts::new_with_config_for_tests(
2017            Vec::new(),
2018            &ClusterType::Development,
2019            AccountSecondaryIndexes::default(),
2020            false,
2021            AccountShrinkThreshold::default(),
2022        );
2023        let mut error_counters = ErrorCounters::default();
2024        let ancestors = vec![(0, 0)].into_iter().collect();
2025
2026        let keypair = Keypair::new();
2027        let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
2028        account.set_executable(true);
2029        accounts.store_slow_uncached(0, &keypair.pubkey(), &account);
2030
2031        assert_eq!(
2032            accounts.load_executable_accounts(
2033                &ancestors,
2034                &mut vec![(keypair.pubkey(), account)],
2035                0,
2036                &mut error_counters,
2037            ),
2038            Err(TransactionError::ProgramAccountNotFound)
2039        );
2040        assert_eq!(error_counters.account_not_found, 1);
2041    }
2042
2043    #[test]
2044    #[should_panic]
2045    fn test_accounts_empty_bank_hash() {
2046        let accounts = Accounts::new_with_config_for_tests(
2047            Vec::new(),
2048            &ClusterType::Development,
2049            AccountSecondaryIndexes::default(),
2050            false,
2051            AccountShrinkThreshold::default(),
2052        );
2053        accounts.bank_hash_at(1);
2054    }
2055
2056    #[test]
2057    fn test_accounts_locks() {
2058        let keypair0 = Keypair::new();
2059        let keypair1 = Keypair::new();
2060        let keypair2 = Keypair::new();
2061        let keypair3 = Keypair::new();
2062
2063        let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2064        let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2065        let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2066        let account3 = AccountSharedData::new(4, 0, &Pubkey::default());
2067
2068        let accounts = Accounts::new_with_config_for_tests(
2069            Vec::new(),
2070            &ClusterType::Development,
2071            AccountSecondaryIndexes::default(),
2072            false,
2073            AccountShrinkThreshold::default(),
2074        );
2075        accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2076        accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2077        accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2078        accounts.store_slow_uncached(0, &keypair3.pubkey(), &account3);
2079
2080        let demote_program_write_locks = true;
2081
2082        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2083        let message = Message::new_with_compiled_instructions(
2084            1,
2085            0,
2086            2,
2087            vec![keypair0.pubkey(), keypair1.pubkey(), native_loader::id()],
2088            Hash::default(),
2089            instructions,
2090        );
2091        let tx = new_sanitized_tx(&[&keypair0], message, Hash::default());
2092        let results0 = accounts.lock_accounts([tx.clone()].iter(), demote_program_write_locks);
2093
2094        assert!(results0[0].is_ok());
2095        assert_eq!(
2096            *accounts
2097                .account_locks
2098                .lock()
2099                .unwrap()
2100                .readonly_locks
2101                .get(&keypair1.pubkey())
2102                .unwrap(),
2103            1
2104        );
2105
2106        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2107        let message = Message::new_with_compiled_instructions(
2108            1,
2109            0,
2110            2,
2111            vec![keypair2.pubkey(), keypair1.pubkey(), native_loader::id()],
2112            Hash::default(),
2113            instructions,
2114        );
2115        let tx0 = new_sanitized_tx(&[&keypair2], message, Hash::default());
2116        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2117        let message = Message::new_with_compiled_instructions(
2118            1,
2119            0,
2120            2,
2121            vec![keypair1.pubkey(), keypair3.pubkey(), native_loader::id()],
2122            Hash::default(),
2123            instructions,
2124        );
2125        let tx1 = new_sanitized_tx(&[&keypair1], message, Hash::default());
2126        let txs = vec![tx0, tx1];
2127        let results1 = accounts.lock_accounts(txs.iter(), demote_program_write_locks);
2128
2129        assert!(results1[0].is_ok()); // Read-only account (keypair1) can be referenced multiple times
2130        assert!(results1[1].is_err()); // Read-only account (keypair1) cannot also be locked as writable
2131        assert_eq!(
2132            *accounts
2133                .account_locks
2134                .lock()
2135                .unwrap()
2136                .readonly_locks
2137                .get(&keypair1.pubkey())
2138                .unwrap(),
2139            2
2140        );
2141
2142        accounts.unlock_accounts([tx].iter(), &results0, demote_program_write_locks);
2143        accounts.unlock_accounts(txs.iter(), &results1, demote_program_write_locks);
2144        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2145        let message = Message::new_with_compiled_instructions(
2146            1,
2147            0,
2148            2,
2149            vec![keypair1.pubkey(), keypair3.pubkey(), native_loader::id()],
2150            Hash::default(),
2151            instructions,
2152        );
2153        let tx = new_sanitized_tx(&[&keypair1], message, Hash::default());
2154        let results2 = accounts.lock_accounts([tx].iter(), demote_program_write_locks);
2155        assert!(results2[0].is_ok()); // Now keypair1 account can be locked as writable
2156
2157        // Check that read-only lock with zero references is deleted
2158        assert!(accounts
2159            .account_locks
2160            .lock()
2161            .unwrap()
2162            .readonly_locks
2163            .get(&keypair1.pubkey())
2164            .is_none());
2165    }
2166
2167    #[test]
2168    fn test_accounts_locks_multithreaded() {
2169        let counter = Arc::new(AtomicU64::new(0));
2170        let exit = Arc::new(AtomicBool::new(false));
2171
2172        let keypair0 = Keypair::new();
2173        let keypair1 = Keypair::new();
2174        let keypair2 = Keypair::new();
2175
2176        let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2177        let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2178        let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2179
2180        let accounts = Accounts::new_with_config_for_tests(
2181            Vec::new(),
2182            &ClusterType::Development,
2183            AccountSecondaryIndexes::default(),
2184            false,
2185            AccountShrinkThreshold::default(),
2186        );
2187        accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2188        accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2189        accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2190
2191        let demote_program_write_locks = true;
2192
2193        let accounts_arc = Arc::new(accounts);
2194
2195        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2196        let readonly_message = Message::new_with_compiled_instructions(
2197            1,
2198            0,
2199            2,
2200            vec![keypair0.pubkey(), keypair1.pubkey(), native_loader::id()],
2201            Hash::default(),
2202            instructions,
2203        );
2204        let readonly_tx = new_sanitized_tx(&[&keypair0], readonly_message, Hash::default());
2205
2206        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2207        let writable_message = Message::new_with_compiled_instructions(
2208            1,
2209            0,
2210            2,
2211            vec![keypair1.pubkey(), keypair2.pubkey(), native_loader::id()],
2212            Hash::default(),
2213            instructions,
2214        );
2215        let writable_tx = new_sanitized_tx(&[&keypair1], writable_message, Hash::default());
2216
2217        let counter_clone = counter.clone();
2218        let accounts_clone = accounts_arc.clone();
2219        let exit_clone = exit.clone();
2220        thread::spawn(move || {
2221            let counter_clone = counter_clone.clone();
2222            let exit_clone = exit_clone.clone();
2223            loop {
2224                let txs = vec![writable_tx.clone()];
2225                let results = accounts_clone
2226                    .clone()
2227                    .lock_accounts(txs.iter(), demote_program_write_locks);
2228                for result in results.iter() {
2229                    if result.is_ok() {
2230                        counter_clone.clone().fetch_add(1, Ordering::SeqCst);
2231                    }
2232                }
2233                accounts_clone.unlock_accounts(txs.iter(), &results, demote_program_write_locks);
2234                if exit_clone.clone().load(Ordering::Relaxed) {
2235                    break;
2236                }
2237            }
2238        });
2239        let counter_clone = counter;
2240        for _ in 0..5 {
2241            let txs = vec![readonly_tx.clone()];
2242            let results = accounts_arc
2243                .clone()
2244                .lock_accounts(txs.iter(), demote_program_write_locks);
2245            if results[0].is_ok() {
2246                let counter_value = counter_clone.clone().load(Ordering::SeqCst);
2247                thread::sleep(time::Duration::from_millis(50));
2248                assert_eq!(counter_value, counter_clone.clone().load(Ordering::SeqCst));
2249            }
2250            accounts_arc.unlock_accounts(txs.iter(), &results, demote_program_write_locks);
2251            thread::sleep(time::Duration::from_millis(50));
2252        }
2253        exit.store(true, Ordering::Relaxed);
2254    }
2255
2256    #[test]
2257    fn test_demote_program_write_locks() {
2258        let keypair0 = Keypair::new();
2259        let keypair1 = Keypair::new();
2260        let keypair2 = Keypair::new();
2261        let keypair3 = Keypair::new();
2262
2263        let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2264        let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2265        let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2266        let account3 = AccountSharedData::new(4, 0, &Pubkey::default());
2267
2268        let accounts = Accounts::new_with_config_for_tests(
2269            Vec::new(),
2270            &ClusterType::Development,
2271            AccountSecondaryIndexes::default(),
2272            false,
2273            AccountShrinkThreshold::default(),
2274        );
2275        accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2276        accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2277        accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2278        accounts.store_slow_uncached(0, &keypair3.pubkey(), &account3);
2279
2280        let demote_program_write_locks = true;
2281
2282        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2283        let message = Message::new_with_compiled_instructions(
2284            1,
2285            0,
2286            0, // All accounts marked as writable
2287            vec![keypair0.pubkey(), keypair1.pubkey(), native_loader::id()],
2288            Hash::default(),
2289            instructions,
2290        );
2291        let tx = new_sanitized_tx(&[&keypair0], message, Hash::default());
2292        let results0 = accounts.lock_accounts([tx].iter(), demote_program_write_locks);
2293
2294        assert!(results0[0].is_ok());
2295        // Instruction program-id account demoted to readonly
2296        assert_eq!(
2297            *accounts
2298                .account_locks
2299                .lock()
2300                .unwrap()
2301                .readonly_locks
2302                .get(&native_loader::id())
2303                .unwrap(),
2304            1
2305        );
2306        // Non-program accounts remain writable
2307        assert!(accounts
2308            .account_locks
2309            .lock()
2310            .unwrap()
2311            .write_locks
2312            .contains(&keypair0.pubkey()));
2313        assert!(accounts
2314            .account_locks
2315            .lock()
2316            .unwrap()
2317            .write_locks
2318            .contains(&keypair1.pubkey()));
2319    }
2320
2321    #[test]
2322    fn test_collect_accounts_to_store() {
2323        let keypair0 = Keypair::new();
2324        let keypair1 = Keypair::new();
2325        let pubkey = gemachain_sdk::pubkey::new_rand();
2326        let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2327        let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2328        let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2329
2330        let rent_collector = RentCollector::default();
2331
2332        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2333        let message = Message::new_with_compiled_instructions(
2334            1,
2335            0,
2336            2,
2337            vec![keypair0.pubkey(), pubkey, native_loader::id()],
2338            Hash::default(),
2339            instructions,
2340        );
2341        let transaction_accounts0 = vec![
2342            (message.account_keys[0], account0),
2343            (message.account_keys[1], account2.clone()),
2344        ];
2345        let tx0 = new_sanitized_tx(&[&keypair0], message, Hash::default());
2346
2347        let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2348        let message = Message::new_with_compiled_instructions(
2349            1,
2350            0,
2351            2,
2352            vec![keypair1.pubkey(), pubkey, native_loader::id()],
2353            Hash::default(),
2354            instructions,
2355        );
2356        let transaction_accounts1 = vec![
2357            (message.account_keys[0], account1),
2358            (message.account_keys[1], account2),
2359        ];
2360        let tx1 = new_sanitized_tx(&[&keypair1], message, Hash::default());
2361
2362        let loaded0 = (
2363            Ok(LoadedTransaction {
2364                accounts: transaction_accounts0,
2365                program_indices: vec![],
2366                rent: 0,
2367                rent_debits: RentDebits::default(),
2368            }),
2369            None,
2370        );
2371
2372        let loaded1 = (
2373            Ok(LoadedTransaction {
2374                accounts: transaction_accounts1,
2375                program_indices: vec![],
2376                rent: 0,
2377                rent_debits: RentDebits::default(),
2378            }),
2379            None,
2380        );
2381
2382        let mut loaded = vec![loaded0, loaded1];
2383
2384        let accounts = Accounts::new_with_config_for_tests(
2385            Vec::new(),
2386            &ClusterType::Development,
2387            AccountSecondaryIndexes::default(),
2388            false,
2389            AccountShrinkThreshold::default(),
2390        );
2391        {
2392            accounts
2393                .account_locks
2394                .lock()
2395                .unwrap()
2396                .insert_new_readonly(&pubkey);
2397        }
2398        let txs = vec![tx0, tx1];
2399        let programs = vec![(Ok(()), None), (Ok(()), None)];
2400        let collected_accounts = accounts.collect_accounts_to_store(
2401            &txs,
2402            &programs,
2403            loaded.as_mut_slice(),
2404            &rent_collector,
2405            &(Hash::default(), FeeCalculator::default()),
2406            true,
2407            true, // merge_nonce_error_into_system_error
2408            true, // demote_program_write_locks
2409        );
2410        assert_eq!(collected_accounts.len(), 2);
2411        assert!(collected_accounts
2412            .iter()
2413            .any(|(pubkey, _account)| *pubkey == &keypair0.pubkey()));
2414        assert!(collected_accounts
2415            .iter()
2416            .any(|(pubkey, _account)| *pubkey == &keypair1.pubkey()));
2417
2418        // Ensure readonly_lock reflects lock
2419        assert_eq!(
2420            *accounts
2421                .account_locks
2422                .lock()
2423                .unwrap()
2424                .readonly_locks
2425                .get(&pubkey)
2426                .unwrap(),
2427            1
2428        );
2429    }
2430
2431    #[test]
2432    fn huge_clean() {
2433        gemachain_logger::setup();
2434        let accounts = Accounts::new_with_config_for_tests(
2435            Vec::new(),
2436            &ClusterType::Development,
2437            AccountSecondaryIndexes::default(),
2438            false,
2439            AccountShrinkThreshold::default(),
2440        );
2441        let mut old_pubkey = Pubkey::default();
2442        let zero_account = AccountSharedData::new(0, 0, AccountSharedData::default().owner());
2443        info!("storing..");
2444        for i in 0..2_000 {
2445            let pubkey = gemachain_sdk::pubkey::new_rand();
2446            let account =
2447                AccountSharedData::new((i + 1) as u64, 0, AccountSharedData::default().owner());
2448            accounts.store_slow_uncached(i, &pubkey, &account);
2449            accounts.store_slow_uncached(i, &old_pubkey, &zero_account);
2450            old_pubkey = pubkey;
2451            accounts.add_root(i);
2452            if i % 1_000 == 0 {
2453                info!("  store {}", i);
2454            }
2455        }
2456        info!("done..cleaning..");
2457        accounts.accounts_db.clean_accounts(None, false, None);
2458    }
2459
2460    fn load_accounts_no_store(accounts: &Accounts, tx: Transaction) -> Vec<TransactionLoadResult> {
2461        let tx = SanitizedTransaction::try_from(tx).unwrap();
2462        let rent_collector = RentCollector::default();
2463        let fee_calculator = FeeCalculator::new(10);
2464        let mut hash_queue = BlockhashQueue::new(100);
2465        hash_queue.register_hash(tx.message().recent_blockhash(), &fee_calculator);
2466
2467        let ancestors = vec![(0, 0)].into_iter().collect();
2468        let mut error_counters = ErrorCounters::default();
2469        accounts.load_accounts(
2470            &ancestors,
2471            &[tx],
2472            vec![(Ok(()), None)],
2473            &hash_queue,
2474            &mut error_counters,
2475            &rent_collector,
2476            &FeatureSet::all_enabled(),
2477        )
2478    }
2479
2480    #[test]
2481    fn test_instructions() {
2482        gemachain_logger::setup();
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
2491        let instructions_key = gemachain_sdk::sysvar::instructions::id();
2492        let keypair = Keypair::new();
2493        let instructions = vec![CompiledInstruction::new(1, &(), vec![0, 1])];
2494        let tx = Transaction::new_with_compiled_instructions(
2495            &[&keypair],
2496            &[gemachain_sdk::pubkey::new_rand(), instructions_key],
2497            Hash::default(),
2498            vec![native_loader::id()],
2499            instructions,
2500        );
2501
2502        let loaded_accounts = load_accounts_no_store(&accounts, tx);
2503        assert_eq!(loaded_accounts.len(), 1);
2504        assert!(loaded_accounts[0].0.is_err());
2505    }
2506
2507    fn create_accounts_prepare_if_nonce_account() -> (
2508        Pubkey,
2509        AccountSharedData,
2510        AccountSharedData,
2511        Hash,
2512        FeeCalculator,
2513        Option<AccountSharedData>,
2514    ) {
2515        let data = nonce::state::Versions::new_current(nonce::State::Initialized(
2516            nonce::state::Data::default(),
2517        ));
2518        let account = AccountSharedData::new_data(42, &data, &system_program::id()).unwrap();
2519        let mut pre_account = account.clone();
2520        pre_account.set_carats(43);
2521        (
2522            Pubkey::default(),
2523            pre_account,
2524            account,
2525            Hash::new(&[1u8; 32]),
2526            FeeCalculator {
2527                carats_per_signature: 1234,
2528            },
2529            None,
2530        )
2531    }
2532
2533    fn run_prepare_if_nonce_account_test(
2534        account: &mut AccountSharedData,
2535        account_pubkey: &Pubkey,
2536        tx_result: &Result<()>,
2537        maybe_nonce_rollback: Option<(
2538            &Pubkey,
2539            &AccountSharedData,
2540            Option<&AccountSharedData>,
2541            bool,
2542        )>,
2543        last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
2544        expect_account: &AccountSharedData,
2545    ) -> bool {
2546        // Verify expect_account's relationship
2547        match maybe_nonce_rollback {
2548            Some((nonce_pubkey, _nonce_account, _maybe_fee_account, _))
2549                if nonce_pubkey == account_pubkey && tx_result.is_ok() =>
2550            {
2551                assert_eq!(expect_account, account) // Account update occurs in system_instruction_processor
2552            }
2553            Some((nonce_pubkey, nonce_account, _maybe_fee_account, _))
2554                if nonce_pubkey == account_pubkey =>
2555            {
2556                assert_ne!(expect_account, nonce_account)
2557            }
2558            _ => assert_eq!(expect_account, account),
2559        }
2560
2561        prepare_if_nonce_account(
2562            account,
2563            account_pubkey,
2564            tx_result,
2565            maybe_nonce_rollback,
2566            last_blockhash_with_fee_calculator,
2567        );
2568        expect_account == account
2569    }
2570
2571    #[test]
2572    fn test_prepare_if_nonce_account_expected() {
2573        let (
2574            pre_account_pubkey,
2575            pre_account,
2576            mut post_account,
2577            last_blockhash,
2578            last_fee_calculator,
2579            maybe_fee_account,
2580        ) = create_accounts_prepare_if_nonce_account();
2581        let post_account_pubkey = pre_account_pubkey;
2582
2583        let mut expect_account = post_account.clone();
2584        let data = nonce::state::Versions::new_current(nonce::State::Initialized(
2585            nonce::state::Data::default(),
2586        ));
2587        expect_account.set_state(&data).unwrap();
2588
2589        assert!(run_prepare_if_nonce_account_test(
2590            &mut post_account,
2591            &post_account_pubkey,
2592            &Ok(()),
2593            Some((
2594                &pre_account_pubkey,
2595                &pre_account,
2596                maybe_fee_account.as_ref(),
2597                false,
2598            )),
2599            &(last_blockhash, last_fee_calculator),
2600            &expect_account,
2601        ));
2602    }
2603
2604    #[test]
2605    fn test_prepare_if_nonce_account_not_nonce_tx() {
2606        let (
2607            pre_account_pubkey,
2608            _pre_account,
2609            _post_account,
2610            last_blockhash,
2611            last_fee_calculator,
2612            _maybe_fee_account,
2613        ) = create_accounts_prepare_if_nonce_account();
2614        let post_account_pubkey = pre_account_pubkey;
2615
2616        let mut post_account = AccountSharedData::default();
2617        let expect_account = post_account.clone();
2618        assert!(run_prepare_if_nonce_account_test(
2619            &mut post_account,
2620            &post_account_pubkey,
2621            &Ok(()),
2622            None,
2623            &(last_blockhash, last_fee_calculator),
2624            &expect_account,
2625        ));
2626    }
2627
2628    #[test]
2629    fn test_prepare_if_nonce_account_not_nonce_pubkey() {
2630        let (
2631            pre_account_pubkey,
2632            pre_account,
2633            mut post_account,
2634            last_blockhash,
2635            last_fee_calculator,
2636            maybe_fee_account,
2637        ) = create_accounts_prepare_if_nonce_account();
2638
2639        let expect_account = post_account.clone();
2640        // Wrong key
2641        assert!(run_prepare_if_nonce_account_test(
2642            &mut post_account,
2643            &Pubkey::new(&[1u8; 32]),
2644            &Ok(()),
2645            Some((
2646                &pre_account_pubkey,
2647                &pre_account,
2648                maybe_fee_account.as_ref(),
2649                true,
2650            )),
2651            &(last_blockhash, last_fee_calculator),
2652            &expect_account,
2653        ));
2654    }
2655
2656    #[test]
2657    fn test_prepare_if_nonce_account_tx_error() {
2658        let (
2659            pre_account_pubkey,
2660            pre_account,
2661            mut post_account,
2662            last_blockhash,
2663            last_fee_calculator,
2664            maybe_fee_account,
2665        ) = create_accounts_prepare_if_nonce_account();
2666        let post_account_pubkey = pre_account_pubkey;
2667
2668        let mut expect_account = pre_account.clone();
2669        expect_account
2670            .set_state(&nonce::state::Versions::new_current(
2671                nonce::State::Initialized(nonce::state::Data {
2672                    blockhash: last_blockhash,
2673                    fee_calculator: last_fee_calculator.clone(),
2674                    ..nonce::state::Data::default()
2675                }),
2676            ))
2677            .unwrap();
2678
2679        assert!(run_prepare_if_nonce_account_test(
2680            &mut post_account,
2681            &post_account_pubkey,
2682            &Err(TransactionError::InstructionError(
2683                0,
2684                InstructionError::InvalidArgument,
2685            )),
2686            Some((
2687                &pre_account_pubkey,
2688                &pre_account,
2689                maybe_fee_account.as_ref(),
2690                true,
2691            )),
2692            &(last_blockhash, last_fee_calculator),
2693            &expect_account,
2694        ));
2695    }
2696
2697    #[test]
2698    fn test_nonced_failure_accounts_rollback_from_pays() {
2699        let rent_collector = RentCollector::default();
2700
2701        let nonce_address = Pubkey::new_unique();
2702        let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
2703        let from = keypair_from_seed(&[1; 32]).unwrap();
2704        let from_address = from.pubkey();
2705        let to_address = Pubkey::new_unique();
2706        let nonce_state =
2707            nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
2708                authority: nonce_authority.pubkey(),
2709                blockhash: Hash::new_unique(),
2710                fee_calculator: FeeCalculator::default(),
2711            }));
2712        let nonce_account_post =
2713            AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
2714        let from_account_post = AccountSharedData::new(4199, 0, &Pubkey::default());
2715        let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
2716        let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
2717        let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
2718
2719        let instructions = vec![
2720            system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
2721            system_instruction::transfer(&from_address, &to_address, 42),
2722        ];
2723        let message = Message::new(&instructions, Some(&from_address));
2724        let blockhash = Hash::new_unique();
2725        let transaction_accounts = vec![
2726            (message.account_keys[0], from_account_post),
2727            (message.account_keys[1], nonce_authority_account),
2728            (message.account_keys[2], nonce_account_post),
2729            (message.account_keys[3], to_account),
2730            (message.account_keys[4], recent_blockhashes_sysvar_account),
2731        ];
2732        let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash);
2733
2734        let nonce_state =
2735            nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
2736                authority: nonce_authority.pubkey(),
2737                blockhash,
2738                fee_calculator: FeeCalculator::default(),
2739            }));
2740        let nonce_account_pre =
2741            AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap();
2742        let from_account_pre = AccountSharedData::new(4242, 0, &Pubkey::default());
2743
2744        let nonce_rollback = Some(NonceRollbackFull::new(
2745            nonce_address,
2746            nonce_account_pre.clone(),
2747            Some(from_account_pre.clone()),
2748        ));
2749
2750        let loaded = (
2751            Ok(LoadedTransaction {
2752                accounts: transaction_accounts,
2753                program_indices: vec![],
2754                rent: 0,
2755                rent_debits: RentDebits::default(),
2756            }),
2757            nonce_rollback.clone(),
2758        );
2759
2760        let mut loaded = vec![loaded];
2761
2762        let next_blockhash = Hash::new_unique();
2763        let accounts = Accounts::new_with_config_for_tests(
2764            Vec::new(),
2765            &ClusterType::Development,
2766            AccountSecondaryIndexes::default(),
2767            false,
2768            AccountShrinkThreshold::default(),
2769        );
2770        let txs = vec![tx];
2771        let programs = vec![(
2772            Err(TransactionError::InstructionError(
2773                1,
2774                InstructionError::InvalidArgument,
2775            )),
2776            nonce_rollback,
2777        )];
2778        let collected_accounts = accounts.collect_accounts_to_store(
2779            &txs,
2780            &programs,
2781            loaded.as_mut_slice(),
2782            &rent_collector,
2783            &(next_blockhash, FeeCalculator::default()),
2784            true,
2785            true, // merge_nonce_error_into_system_error
2786            true, // demote_program_write_locks
2787        );
2788        assert_eq!(collected_accounts.len(), 2);
2789        assert_eq!(
2790            collected_accounts
2791                .iter()
2792                .find(|(pubkey, _account)| *pubkey == &from_address)
2793                .map(|(_pubkey, account)| *account)
2794                .cloned()
2795                .unwrap(),
2796            from_account_pre,
2797        );
2798        let collected_nonce_account = collected_accounts
2799            .iter()
2800            .find(|(pubkey, _account)| *pubkey == &nonce_address)
2801            .map(|(_pubkey, account)| *account)
2802            .cloned()
2803            .unwrap();
2804        assert_eq!(
2805            collected_nonce_account.carats(),
2806            nonce_account_pre.carats(),
2807        );
2808        assert!(nonce_account::verify_nonce_account(
2809            &collected_nonce_account,
2810            &next_blockhash
2811        ));
2812    }
2813
2814    #[test]
2815    fn test_nonced_failure_accounts_rollback_nonce_pays() {
2816        let rent_collector = RentCollector::default();
2817
2818        let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
2819        let nonce_address = nonce_authority.pubkey();
2820        let from = keypair_from_seed(&[1; 32]).unwrap();
2821        let from_address = from.pubkey();
2822        let to_address = Pubkey::new_unique();
2823        let nonce_state =
2824            nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
2825                authority: nonce_authority.pubkey(),
2826                blockhash: Hash::new_unique(),
2827                fee_calculator: FeeCalculator::default(),
2828            }));
2829        let nonce_account_post =
2830            AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
2831        let from_account_post = AccountSharedData::new(4200, 0, &Pubkey::default());
2832        let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
2833        let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
2834        let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
2835
2836        let instructions = vec![
2837            system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
2838            system_instruction::transfer(&from_address, &to_address, 42),
2839        ];
2840        let message = Message::new(&instructions, Some(&nonce_address));
2841        let blockhash = Hash::new_unique();
2842        let transaction_accounts = vec![
2843            (message.account_keys[0], from_account_post),
2844            (message.account_keys[1], nonce_authority_account),
2845            (message.account_keys[2], nonce_account_post),
2846            (message.account_keys[3], to_account),
2847            (message.account_keys[4], recent_blockhashes_sysvar_account),
2848        ];
2849        let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash);
2850
2851        let nonce_state =
2852            nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
2853                authority: nonce_authority.pubkey(),
2854                blockhash,
2855                fee_calculator: FeeCalculator::default(),
2856            }));
2857        let nonce_account_pre =
2858            AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap();
2859
2860        let nonce_rollback = Some(NonceRollbackFull::new(
2861            nonce_address,
2862            nonce_account_pre.clone(),
2863            None,
2864        ));
2865
2866        let loaded = (
2867            Ok(LoadedTransaction {
2868                accounts: transaction_accounts,
2869                program_indices: vec![],
2870                rent: 0,
2871                rent_debits: RentDebits::default(),
2872            }),
2873            nonce_rollback.clone(),
2874        );
2875
2876        let mut loaded = vec![loaded];
2877
2878        let next_blockhash = Hash::new_unique();
2879        let accounts = Accounts::new_with_config_for_tests(
2880            Vec::new(),
2881            &ClusterType::Development,
2882            AccountSecondaryIndexes::default(),
2883            false,
2884            AccountShrinkThreshold::default(),
2885        );
2886        let txs = vec![tx];
2887        let programs = vec![(
2888            Err(TransactionError::InstructionError(
2889                1,
2890                InstructionError::InvalidArgument,
2891            )),
2892            nonce_rollback,
2893        )];
2894        let collected_accounts = accounts.collect_accounts_to_store(
2895            &txs,
2896            &programs,
2897            loaded.as_mut_slice(),
2898            &rent_collector,
2899            &(next_blockhash, FeeCalculator::default()),
2900            true,
2901            true, // merge_nonce_error_into_system_error
2902            true, // demote_program_write_locks
2903        );
2904        assert_eq!(collected_accounts.len(), 1);
2905        let collected_nonce_account = collected_accounts
2906            .iter()
2907            .find(|(pubkey, _account)| *pubkey == &nonce_address)
2908            .map(|(_pubkey, account)| *account)
2909            .cloned()
2910            .unwrap();
2911        assert_eq!(
2912            collected_nonce_account.carats(),
2913            nonce_account_pre.carats()
2914        );
2915        assert!(nonce_account::verify_nonce_account(
2916            &collected_nonce_account,
2917            &next_blockhash
2918        ));
2919    }
2920
2921    #[test]
2922    fn test_load_largest_accounts() {
2923        let accounts = Accounts::new_with_config_for_tests(
2924            Vec::new(),
2925            &ClusterType::Development,
2926            AccountSecondaryIndexes::default(),
2927            false,
2928            AccountShrinkThreshold::default(),
2929        );
2930
2931        let pubkey0 = Pubkey::new_unique();
2932        let account0 = AccountSharedData::new(42, 0, &Pubkey::default());
2933        accounts.store_slow_uncached(0, &pubkey0, &account0);
2934        let pubkey1 = Pubkey::new_unique();
2935        let account1 = AccountSharedData::new(42, 0, &Pubkey::default());
2936        accounts.store_slow_uncached(0, &pubkey1, &account1);
2937        let pubkey2 = Pubkey::new_unique();
2938        let account2 = AccountSharedData::new(41, 0, &Pubkey::default());
2939        accounts.store_slow_uncached(0, &pubkey2, &account2);
2940
2941        let ancestors = vec![(0, 0)].into_iter().collect();
2942        let all_pubkeys: HashSet<_> = vec![pubkey0, pubkey1, pubkey2].into_iter().collect();
2943
2944        // num == 0 should always return empty set
2945        let bank_id = 0;
2946        assert_eq!(
2947            accounts
2948                .load_largest_accounts(
2949                    &ancestors,
2950                    bank_id,
2951                    0,
2952                    &HashSet::new(),
2953                    AccountAddressFilter::Exclude
2954                )
2955                .unwrap(),
2956            vec![]
2957        );
2958        assert_eq!(
2959            accounts
2960                .load_largest_accounts(
2961                    &ancestors,
2962                    bank_id,
2963                    0,
2964                    &all_pubkeys,
2965                    AccountAddressFilter::Include
2966                )
2967                .unwrap(),
2968            vec![]
2969        );
2970
2971        // list should be sorted by balance, then pubkey, descending
2972        assert!(pubkey1 > pubkey0);
2973        assert_eq!(
2974            accounts
2975                .load_largest_accounts(
2976                    &ancestors,
2977                    bank_id,
2978                    1,
2979                    &HashSet::new(),
2980                    AccountAddressFilter::Exclude
2981                )
2982                .unwrap(),
2983            vec![(pubkey1, 42)]
2984        );
2985        assert_eq!(
2986            accounts
2987                .load_largest_accounts(
2988                    &ancestors,
2989                    bank_id,
2990                    2,
2991                    &HashSet::new(),
2992                    AccountAddressFilter::Exclude
2993                )
2994                .unwrap(),
2995            vec![(pubkey1, 42), (pubkey0, 42)]
2996        );
2997        assert_eq!(
2998            accounts
2999                .load_largest_accounts(
3000                    &ancestors,
3001                    bank_id,
3002                    3,
3003                    &HashSet::new(),
3004                    AccountAddressFilter::Exclude
3005                )
3006                .unwrap(),
3007            vec![(pubkey1, 42), (pubkey0, 42), (pubkey2, 41)]
3008        );
3009
3010        // larger num should not affect results
3011        assert_eq!(
3012            accounts
3013                .load_largest_accounts(
3014                    &ancestors,
3015                    bank_id,
3016                    6,
3017                    &HashSet::new(),
3018                    AccountAddressFilter::Exclude
3019                )
3020                .unwrap(),
3021            vec![(pubkey1, 42), (pubkey0, 42), (pubkey2, 41)]
3022        );
3023
3024        // AccountAddressFilter::Exclude should exclude entry
3025        let exclude1: HashSet<_> = vec![pubkey1].into_iter().collect();
3026        assert_eq!(
3027            accounts
3028                .load_largest_accounts(
3029                    &ancestors,
3030                    bank_id,
3031                    1,
3032                    &exclude1,
3033                    AccountAddressFilter::Exclude
3034                )
3035                .unwrap(),
3036            vec![(pubkey0, 42)]
3037        );
3038        assert_eq!(
3039            accounts
3040                .load_largest_accounts(
3041                    &ancestors,
3042                    bank_id,
3043                    2,
3044                    &exclude1,
3045                    AccountAddressFilter::Exclude
3046                )
3047                .unwrap(),
3048            vec![(pubkey0, 42), (pubkey2, 41)]
3049        );
3050        assert_eq!(
3051            accounts
3052                .load_largest_accounts(
3053                    &ancestors,
3054                    bank_id,
3055                    3,
3056                    &exclude1,
3057                    AccountAddressFilter::Exclude
3058                )
3059                .unwrap(),
3060            vec![(pubkey0, 42), (pubkey2, 41)]
3061        );
3062
3063        // AccountAddressFilter::Include should limit entries
3064        let include1_2: HashSet<_> = vec![pubkey1, pubkey2].into_iter().collect();
3065        assert_eq!(
3066            accounts
3067                .load_largest_accounts(
3068                    &ancestors,
3069                    bank_id,
3070                    1,
3071                    &include1_2,
3072                    AccountAddressFilter::Include
3073                )
3074                .unwrap(),
3075            vec![(pubkey1, 42)]
3076        );
3077        assert_eq!(
3078            accounts
3079                .load_largest_accounts(
3080                    &ancestors,
3081                    bank_id,
3082                    2,
3083                    &include1_2,
3084                    AccountAddressFilter::Include
3085                )
3086                .unwrap(),
3087            vec![(pubkey1, 42), (pubkey2, 41)]
3088        );
3089        assert_eq!(
3090            accounts
3091                .load_largest_accounts(
3092                    &ancestors,
3093                    bank_id,
3094                    3,
3095                    &include1_2,
3096                    AccountAddressFilter::Include
3097                )
3098                .unwrap(),
3099            vec![(pubkey1, 42), (pubkey2, 41)]
3100        );
3101    }
3102}