solana_runtime/
bank.rs

1//! The `bank` module tracks client accounts and the progress of on-chain
2//! programs.
3//!
4//! A single bank relates to a block produced by a single leader and each bank
5//! except for the genesis bank points back to a parent bank.
6//!
7//! The bank is the main entrypoint for processing verified transactions with the function
8//! `Bank::process_transactions`
9//!
10//! It does this by loading the accounts using the reference it holds on the account store,
11//! and then passing those to an InvokeContext which handles loading the programs specified
12//! by the Transaction and executing it.
13//!
14//! The bank then stores the results to the accounts store.
15//!
16//! It then has apis for retrieving if a transaction has been processed and it's status.
17//! See `get_signature_status` et al.
18//!
19//! Bank lifecycle:
20//!
21//! A bank is newly created and open to transactions. Transactions are applied
22//! until either the bank reached the tick count when the node is the leader for that slot, or the
23//! node has applied all transactions present in all `Entry`s in the slot.
24//!
25//! Once it is complete, the bank can then be frozen. After frozen, no more transactions can
26//! be applied or state changes made. At the frozen step, rent will be applied and various
27//! sysvar special accounts update to the new state of the system.
28//!
29//! After frozen, and the bank has had the appropriate number of votes on it, then it can become
30//! rooted. At this point, it will not be able to be removed from the chain and the
31//! state is finalized.
32//!
33//! It offers a high-level API that signs transactions
34//! on behalf of the caller, and a low-level API for when they have
35//! already been signed and verified.
36#[allow(deprecated)]
37use solana_sdk::recent_blockhashes_account;
38pub use solana_sdk::reward_type::RewardType;
39use {
40    crate::{
41        account_overrides::AccountOverrides,
42        accounts::{
43            AccountAddressFilter, Accounts, LoadedTransaction, PubkeyAccountSlot,
44            TransactionLoadResult,
45        },
46        accounts_db::{
47            AccountShrinkThreshold, AccountsDbConfig, SnapshotStorages,
48            ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING,
49        },
50        accounts_index::{AccountSecondaryIndexes, IndexKey, ScanConfig, ScanResult, ZeroLamport},
51        accounts_update_notifier_interface::AccountsUpdateNotifier,
52        ancestors::{Ancestors, AncestorsForSerialization},
53        blockhash_queue::BlockhashQueue,
54        builtins::{self, BuiltinAction, BuiltinFeatureTransition, Builtins},
55        cost_tracker::CostTracker,
56        epoch_stakes::{EpochStakes, NodeVoteAccounts},
57        inline_safe_associated_token_account, inline_safe_token,
58        message_processor::MessageProcessor,
59        rent_collector::{CollectedInfo, RentCollector},
60        stake_account::{self, StakeAccount},
61        stake_weighted_timestamp::{
62            calculate_stake_weighted_timestamp, MaxAllowableDrift,
63            MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST, MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
64        },
65        stakes::{InvalidCacheEntryReason, Stakes, StakesCache, StakesEnum},
66        status_cache::{SlotDelta, StatusCache},
67        storable_accounts::StorableAccounts,
68        system_instruction_processor::{get_system_account_kind, SystemAccountKind},
69        transaction_batch::TransactionBatch,
70        transaction_error_metrics::TransactionErrorMetrics,
71        vote_account::{VoteAccount, VoteAccountsHashMap},
72        vote_parser,
73    },
74    byteorder::{ByteOrder, LittleEndian},
75    dashmap::{DashMap, DashSet},
76    itertools::Itertools,
77    log::*,
78    rayon::{
79        iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator},
80        ThreadPool, ThreadPoolBuilder,
81    },
82    safecoin_measure::{measure, measure::Measure},
83    solana_metrics::{inc_new_counter_debug, inc_new_counter_info},
84    solana_program_runtime::{
85        accounts_data_meter::MAX_ACCOUNTS_DATA_LEN,
86        compute_budget::{self, ComputeBudget},
87        executor_cache::{CachedExecutors, Executors, TransactionExecutor, MAX_CACHED_EXECUTORS},
88        invoke_context::{BuiltinProgram, ProcessInstructionWithContext},
89        log_collector::LogCollector,
90        sysvar_cache::SysvarCache,
91        timings::{ExecuteTimingType, ExecuteTimings},
92    },
93    solana_sdk::{
94        account::{
95            create_account_shared_data_with_fields as create_account, from_account, Account,
96            AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
97        },
98        account_utils::StateMut,
99        clock::{
100            BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_TICKS_PER_SECOND,
101            INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE, MAX_TRANSACTION_FORWARDING_DELAY,
102            SECONDS_PER_DAY,
103        },
104        ed25519_program,
105        epoch_info::EpochInfo,
106        epoch_schedule::EpochSchedule,
107        feature,
108        feature_set::{
109            self, add_set_compute_unit_price_ix, default_units_per_instruction,
110            disable_fee_calculator, enable_early_verification_of_account_modifications,
111            enable_request_heap_frame_ix, use_default_units_in_fee_calculation, FeatureSet,
112        },
113        fee::FeeStructure,
114        fee_calculator::{FeeCalculator, FeeRateGovernor},
115        genesis_config::{ClusterType, GenesisConfig},
116        hard_forks::HardForks,
117        hash::{extend_and_hash, hashv, Hash},
118        incinerator,
119        inflation::Inflation,
120        instruction::CompiledInstruction,
121        lamports::LamportsError,
122        message::{AccountKeys, SanitizedMessage},
123        native_loader,
124        native_token::{sol_to_lamports, LAMPORTS_PER_SAFE},
125        nonce::{self, state::DurableNonce, NONCED_TX_MARKER_IX_INDEX},
126        nonce_account,
127        packet::PACKET_DATA_SIZE,
128        precompiles::get_precompiles,
129        pubkey::Pubkey,
130        saturating_add_assign, secp256k1_program,
131        signature::{Keypair, Signature},
132        slot_hashes::SlotHashes,
133        slot_history::{Check, SlotHistory},
134        stake::state::Delegation,
135        system_transaction,
136        sysvar::{self, Sysvar, SysvarId},
137        timing::years_as_slots,
138        transaction::{
139            MessageHash, Result, SanitizedTransaction, Transaction, TransactionError,
140            TransactionVerificationMode, VersionedTransaction, MAX_TX_ACCOUNT_LOCKS,
141        },
142        transaction_context::{
143            ExecutionRecord, InstructionTrace, TransactionAccount, TransactionContext,
144            TransactionReturnData,
145        },
146    },
147    solana_stake_program::stake_state::{
148        self, InflationPointCalculationEvent, PointValue, StakeState,
149    },
150    solana_vote_program::vote_state::{VoteState, VoteStateVersions},
151    std::{
152        borrow::Cow,
153        cell::RefCell,
154        collections::{HashMap, HashSet},
155        convert::{TryFrom, TryInto},
156        fmt, mem,
157        ops::{Deref, RangeInclusive},
158        path::PathBuf,
159        rc::Rc,
160        sync::{
161            atomic::{
162                AtomicBool, AtomicI64, AtomicU64, AtomicUsize,
163                Ordering::{AcqRel, Acquire, Relaxed},
164            },
165            Arc, LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard,
166        },
167        thread::Builder,
168        time::{Duration, Instant},
169    },
170};
171
172/// params to `verify_bank_hash`
173pub struct VerifyBankHash {
174    pub test_hash_calculation: bool,
175    pub can_cached_slot_be_unflushed: bool,
176    pub ignore_mismatch: bool,
177    pub require_rooted_bank: bool,
178    pub run_in_background: bool,
179    pub store_hash_raw_data_for_debug: bool,
180}
181
182#[derive(Debug, Default)]
183struct RewardsMetrics {
184    load_vote_and_stake_accounts_us: AtomicU64,
185    calculate_points_us: AtomicU64,
186    redeem_rewards_us: u64,
187    store_stake_accounts_us: AtomicU64,
188    store_vote_accounts_us: AtomicU64,
189    invalid_cached_vote_accounts: usize,
190    invalid_cached_stake_accounts: usize,
191    invalid_cached_stake_accounts_rent_epoch: usize,
192    vote_accounts_cache_miss_count: usize,
193}
194
195mod address_lookup_table;
196mod builtin_programs;
197mod sysvar_cache;
198mod transaction_account_state_info;
199
200pub const SECONDS_PER_YEAR: f64 = 365.25 * 24.0 * 60.0 * 60.0;
201
202pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5;
203
204pub type Rewrites = RwLock<HashMap<Pubkey, Hash>>;
205
206#[derive(Default)]
207struct RentMetrics {
208    hold_range_us: AtomicU64,
209    load_us: AtomicU64,
210    collect_us: AtomicU64,
211    hash_us: AtomicU64,
212    store_us: AtomicU64,
213    count: AtomicUsize,
214}
215
216#[derive(Clone, Debug, PartialEq, Eq)]
217pub struct RentDebit {
218    rent_collected: u64,
219    post_balance: u64,
220}
221
222impl RentDebit {
223    fn try_into_reward_info(self) -> Option<RewardInfo> {
224        let rent_debit = i64::try_from(self.rent_collected)
225            .ok()
226            .and_then(|r| r.checked_neg());
227        rent_debit.map(|rent_debit| RewardInfo {
228            reward_type: RewardType::Rent,
229            lamports: rent_debit,
230            post_balance: self.post_balance,
231            commission: None, // Not applicable
232        })
233    }
234}
235
236/// Incremental snapshots only calculate their accounts hash based on the account changes WITHIN the incremental slot range.
237/// So, we need to keep track of the full snapshot expected accounts hash results.
238/// We also need to keep track of the hash and capitalization specific to the incremental snapshot slot range.
239/// The capitalization we calculate for the incremental slot will NOT be consistent with the bank's capitalization.
240/// It is not feasible to calculate a capitalization delta that is correct given just incremental slots account data and the full snapshot's capitalization.
241#[derive(Serialize, Deserialize, AbiExample, Clone, Debug, Default, PartialEq, Eq)]
242pub struct BankIncrementalSnapshotPersistence {
243    /// slot of full snapshot
244    pub full_slot: Slot,
245    /// accounts hash from the full snapshot
246    pub full_hash: Hash,
247    /// capitalization from the full snapshot
248    pub full_capitalization: u64,
249    /// hash of the accounts in the incremental snapshot slot range, including zero-lamport accounts
250    pub incremental_hash: Hash,
251    /// capitalization of the accounts in the incremental snapshot slot range
252    pub incremental_capitalization: u64,
253}
254
255#[derive(Clone, Debug, Default, PartialEq, Eq)]
256pub struct RentDebits(HashMap<Pubkey, RentDebit>);
257impl RentDebits {
258    fn get_account_rent_debit(&self, address: &Pubkey) -> u64 {
259        self.0
260            .get(address)
261            .map(|r| r.rent_collected)
262            .unwrap_or_default()
263    }
264
265    pub fn insert(&mut self, address: &Pubkey, rent_collected: u64, post_balance: u64) {
266        if rent_collected != 0 {
267            self.0.insert(
268                *address,
269                RentDebit {
270                    rent_collected,
271                    post_balance,
272                },
273            );
274        }
275    }
276
277    pub fn into_unordered_rewards_iter(self) -> impl Iterator<Item = (Pubkey, RewardInfo)> {
278        self.0
279            .into_iter()
280            .filter_map(|(address, rent_debit)| Some((address, rent_debit.try_into_reward_info()?)))
281    }
282}
283
284pub type BankStatusCache = StatusCache<Result<()>>;
285#[frozen_abi(digest = "HEJXoycXvGT2pwMuKcUKzzbeemnqbfrUC4jHZx1ncaWv")]
286pub type BankSlotDelta = SlotDelta<Result<()>>;
287
288// Eager rent collection repeats in cyclic manner.
289// Each cycle is composed of <partition_count> number of tiny pubkey subranges
290// to scan, which is always multiple of the number of slots in epoch.
291pub(crate) type PartitionIndex = u64;
292pub type PartitionsPerCycle = u64;
293type Partition = (PartitionIndex, PartitionIndex, PartitionsPerCycle);
294type RentCollectionCycleParams = (
295    Epoch,
296    SlotCount,
297    bool,
298    Epoch,
299    EpochCount,
300    PartitionsPerCycle,
301);
302
303pub struct SquashTiming {
304    pub squash_accounts_ms: u64,
305    pub squash_accounts_cache_ms: u64,
306    pub squash_accounts_index_ms: u64,
307    pub squash_accounts_store_ms: u64,
308
309    pub squash_cache_ms: u64,
310}
311
312type EpochCount = u64;
313
314#[derive(Debug)]
315pub struct BankRc {
316    /// where all the Accounts are stored
317    pub accounts: Arc<Accounts>,
318
319    /// Previous checkpoint of this bank
320    pub(crate) parent: RwLock<Option<Arc<Bank>>>,
321
322    /// Current slot
323    pub(crate) slot: Slot,
324
325    pub(crate) bank_id_generator: Arc<AtomicU64>,
326}
327
328#[cfg(RUSTC_WITH_SPECIALIZATION)]
329use safecoin_frozen_abi::abi_example::AbiExample;
330
331#[cfg(RUSTC_WITH_SPECIALIZATION)]
332impl AbiExample for BankRc {
333    fn example() -> Self {
334        BankRc {
335            // Set parent to None to cut the recursion into another Bank
336            parent: RwLock::new(None),
337            // AbiExample for Accounts is specially implemented to contain a storage example
338            accounts: AbiExample::example(),
339            slot: AbiExample::example(),
340            bank_id_generator: Arc::new(AtomicU64::new(0)),
341        }
342    }
343}
344
345impl BankRc {
346    pub(crate) fn new(accounts: Accounts, slot: Slot) -> Self {
347        Self {
348            accounts: Arc::new(accounts),
349            parent: RwLock::new(None),
350            slot,
351            bank_id_generator: Arc::new(AtomicU64::new(0)),
352        }
353    }
354}
355
356pub type TransactionCheckResult = (Result<()>, Option<NoncePartial>);
357
358pub struct TransactionResults {
359    pub fee_collection_results: Vec<Result<()>>,
360    pub execution_results: Vec<TransactionExecutionResult>,
361    pub rent_debits: Vec<RentDebits>,
362}
363
364#[derive(Debug, Clone)]
365pub struct TransactionExecutionDetails {
366    pub status: Result<()>,
367    pub log_messages: Option<Vec<String>>,
368    pub inner_instructions: Option<InnerInstructionsList>,
369    pub durable_nonce_fee: Option<DurableNonceFee>,
370    pub return_data: Option<TransactionReturnData>,
371    pub executed_units: u64,
372    /// The change in accounts data len for this transaction.
373    /// NOTE: This value is valid IFF `status` is `Ok`.
374    pub accounts_data_len_delta: i64,
375}
376
377/// Type safe representation of a transaction execution attempt which
378/// differentiates between a transaction that was executed (will be
379/// committed to the ledger) and a transaction which wasn't executed
380/// and will be dropped.
381///
382/// Note: `Result<TransactionExecutionDetails, TransactionError>` is not
383/// used because it's easy to forget that the inner `details.status` field
384/// is what should be checked to detect a successful transaction. This
385/// enum provides a convenience method `Self::was_executed_successfully` to
386/// make such checks hard to do incorrectly.
387#[derive(Debug, Clone)]
388pub enum TransactionExecutionResult {
389    Executed {
390        details: TransactionExecutionDetails,
391        executors: Rc<RefCell<Executors>>,
392    },
393    NotExecuted(TransactionError),
394}
395
396impl TransactionExecutionResult {
397    pub fn was_executed_successfully(&self) -> bool {
398        match self {
399            Self::Executed { details, .. } => details.status.is_ok(),
400            Self::NotExecuted { .. } => false,
401        }
402    }
403
404    pub fn was_executed(&self) -> bool {
405        match self {
406            Self::Executed { .. } => true,
407            Self::NotExecuted(_) => false,
408        }
409    }
410
411    pub fn details(&self) -> Option<&TransactionExecutionDetails> {
412        match self {
413            Self::Executed { details, .. } => Some(details),
414            Self::NotExecuted(_) => None,
415        }
416    }
417
418    pub fn flattened_result(&self) -> Result<()> {
419        match self {
420            Self::Executed { details, .. } => details.status.clone(),
421            Self::NotExecuted(err) => Err(err.clone()),
422        }
423    }
424}
425
426pub struct LoadAndExecuteTransactionsOutput {
427    pub loaded_transactions: Vec<TransactionLoadResult>,
428    // Vector of results indicating whether a transaction was executed or could not
429    // be executed. Note executed transactions can still have failed!
430    pub execution_results: Vec<TransactionExecutionResult>,
431    pub retryable_transaction_indexes: Vec<usize>,
432    // Total number of transactions that were executed
433    pub executed_transactions_count: usize,
434    // Total number of the executed transactions that returned success/not
435    // an error.
436    pub executed_with_successful_result_count: usize,
437    pub signature_count: u64,
438    pub error_counters: TransactionErrorMetrics,
439}
440
441#[derive(Debug, Clone)]
442pub enum DurableNonceFee {
443    Valid(u64),
444    Invalid,
445}
446
447impl From<&NonceFull> for DurableNonceFee {
448    fn from(nonce: &NonceFull) -> Self {
449        match nonce.lamports_per_signature() {
450            Some(lamports_per_signature) => Self::Valid(lamports_per_signature),
451            None => Self::Invalid,
452        }
453    }
454}
455
456impl DurableNonceFee {
457    pub fn lamports_per_signature(&self) -> Option<u64> {
458        match self {
459            Self::Valid(lamports_per_signature) => Some(*lamports_per_signature),
460            Self::Invalid => None,
461        }
462    }
463}
464
465pub struct TransactionSimulationResult {
466    pub result: Result<()>,
467    pub logs: TransactionLogMessages,
468    pub post_simulation_accounts: Vec<TransactionAccount>,
469    pub units_consumed: u64,
470    pub return_data: Option<TransactionReturnData>,
471}
472pub struct TransactionBalancesSet {
473    pub pre_balances: TransactionBalances,
474    pub post_balances: TransactionBalances,
475}
476
477impl TransactionBalancesSet {
478    pub fn new(pre_balances: TransactionBalances, post_balances: TransactionBalances) -> Self {
479        assert_eq!(pre_balances.len(), post_balances.len());
480        Self {
481            pre_balances,
482            post_balances,
483        }
484    }
485}
486pub type TransactionBalances = Vec<Vec<u64>>;
487
488/// An ordered list of compiled instructions that were invoked during a
489/// transaction instruction
490pub type InnerInstructions = Vec<CompiledInstruction>;
491
492/// A list of compiled instructions that were invoked during each instruction of
493/// a transaction
494pub type InnerInstructionsList = Vec<InnerInstructions>;
495
496/// Convert from an InstructionTrace to InnerInstructionsList
497pub fn inner_instructions_list_from_instruction_trace(
498    instruction_trace: &InstructionTrace,
499) -> InnerInstructionsList {
500    instruction_trace
501        .iter()
502        .map(|inner_instructions_trace| {
503            inner_instructions_trace
504                .iter()
505                .skip(1)
506                .map(|instruction_context| {
507                    CompiledInstruction::new_from_raw_parts(
508                        instruction_context
509                            .get_index_of_program_account_in_transaction(
510                                instruction_context
511                                    .get_number_of_program_accounts()
512                                    .saturating_sub(1),
513                            )
514                            .unwrap_or_default() as u8,
515                        instruction_context.get_instruction_data().to_vec(),
516                        (0..instruction_context.get_number_of_instruction_accounts())
517                            .map(|instruction_account_index| {
518                                instruction_context
519                                    .get_index_of_instruction_account_in_transaction(
520                                        instruction_account_index,
521                                    )
522                                    .unwrap_or_default() as u8
523                            })
524                            .collect(),
525                    )
526                })
527                .collect()
528        })
529        .collect()
530}
531
532/// A list of log messages emitted during a transaction
533pub type TransactionLogMessages = Vec<String>;
534
535#[derive(Serialize, Deserialize, AbiExample, AbiEnumVisitor, Debug, PartialEq, Eq)]
536pub enum TransactionLogCollectorFilter {
537    All,
538    AllWithVotes,
539    None,
540    OnlyMentionedAddresses,
541}
542
543impl Default for TransactionLogCollectorFilter {
544    fn default() -> Self {
545        Self::None
546    }
547}
548
549#[derive(AbiExample, Debug, Default)]
550pub struct TransactionLogCollectorConfig {
551    pub mentioned_addresses: HashSet<Pubkey>,
552    pub filter: TransactionLogCollectorFilter,
553}
554
555#[derive(AbiExample, Clone, Debug, PartialEq, Eq)]
556pub struct TransactionLogInfo {
557    pub signature: Signature,
558    pub result: Result<()>,
559    pub is_vote: bool,
560    pub log_messages: TransactionLogMessages,
561}
562
563#[derive(AbiExample, Default, Debug)]
564pub struct TransactionLogCollector {
565    // All the logs collected for from this Bank.  Exact contents depend on the
566    // active `TransactionLogCollectorFilter`
567    pub logs: Vec<TransactionLogInfo>,
568
569    // For each `mentioned_addresses`, maintain a list of indices into `logs` to easily
570    // locate the logs from transactions that included the mentioned addresses.
571    pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>,
572}
573
574impl TransactionLogCollector {
575    pub fn get_logs_for_address(
576        &self,
577        address: Option<&Pubkey>,
578    ) -> Option<Vec<TransactionLogInfo>> {
579        match address {
580            None => Some(self.logs.clone()),
581            Some(address) => self.mentioned_address_map.get(address).map(|log_indices| {
582                log_indices
583                    .iter()
584                    .filter_map(|i| self.logs.get(*i).cloned())
585                    .collect()
586            }),
587        }
588    }
589}
590
591pub trait NonceInfo {
592    fn address(&self) -> &Pubkey;
593    fn account(&self) -> &AccountSharedData;
594    fn lamports_per_signature(&self) -> Option<u64>;
595    fn fee_payer_account(&self) -> Option<&AccountSharedData>;
596}
597
598/// Holds limited nonce info available during transaction checks
599#[derive(Clone, Debug, Default, PartialEq, Eq)]
600pub struct NoncePartial {
601    address: Pubkey,
602    account: AccountSharedData,
603}
604impl NoncePartial {
605    pub fn new(address: Pubkey, account: AccountSharedData) -> Self {
606        Self { address, account }
607    }
608}
609impl NonceInfo for NoncePartial {
610    fn address(&self) -> &Pubkey {
611        &self.address
612    }
613    fn account(&self) -> &AccountSharedData {
614        &self.account
615    }
616    fn lamports_per_signature(&self) -> Option<u64> {
617        nonce_account::lamports_per_signature_of(&self.account)
618    }
619    fn fee_payer_account(&self) -> Option<&AccountSharedData> {
620        None
621    }
622}
623
624/// Holds fee subtracted nonce info
625#[derive(Clone, Debug, Default, PartialEq, Eq)]
626pub struct NonceFull {
627    address: Pubkey,
628    account: AccountSharedData,
629    fee_payer_account: Option<AccountSharedData>,
630}
631impl NonceFull {
632    pub fn new(
633        address: Pubkey,
634        account: AccountSharedData,
635        fee_payer_account: Option<AccountSharedData>,
636    ) -> Self {
637        Self {
638            address,
639            account,
640            fee_payer_account,
641        }
642    }
643    pub fn from_partial(
644        partial: NoncePartial,
645        message: &SanitizedMessage,
646        accounts: &[TransactionAccount],
647        rent_debits: &RentDebits,
648    ) -> Result<Self> {
649        let fee_payer = (0..message.account_keys().len()).find_map(|i| {
650            if let Some((k, a)) = &accounts.get(i) {
651                if message.is_non_loader_key(i) {
652                    return Some((k, a));
653                }
654            }
655            None
656        });
657
658        if let Some((fee_payer_address, fee_payer_account)) = fee_payer {
659            let mut fee_payer_account = fee_payer_account.clone();
660            let rent_debit = rent_debits.get_account_rent_debit(fee_payer_address);
661            fee_payer_account.set_lamports(fee_payer_account.lamports().saturating_add(rent_debit));
662
663            let nonce_address = *partial.address();
664            if *fee_payer_address == nonce_address {
665                Ok(Self::new(nonce_address, fee_payer_account, None))
666            } else {
667                Ok(Self::new(
668                    nonce_address,
669                    partial.account().clone(),
670                    Some(fee_payer_account),
671                ))
672            }
673        } else {
674            Err(TransactionError::AccountNotFound)
675        }
676    }
677}
678impl NonceInfo for NonceFull {
679    fn address(&self) -> &Pubkey {
680        &self.address
681    }
682    fn account(&self) -> &AccountSharedData {
683        &self.account
684    }
685    fn lamports_per_signature(&self) -> Option<u64> {
686        nonce_account::lamports_per_signature_of(&self.account)
687    }
688    fn fee_payer_account(&self) -> Option<&AccountSharedData> {
689        self.fee_payer_account.as_ref()
690    }
691}
692
693// Bank's common fields shared by all supported snapshot versions for deserialization.
694// Sync fields with BankFieldsToSerialize! This is paired with it.
695// All members are made public to remain Bank's members private and to make versioned deserializer workable on this
696#[derive(Clone, Debug, Default, PartialEq)]
697pub struct BankFieldsToDeserialize {
698    pub(crate) blockhash_queue: BlockhashQueue,
699    pub(crate) ancestors: AncestorsForSerialization,
700    pub(crate) hash: Hash,
701    pub(crate) parent_hash: Hash,
702    pub(crate) parent_slot: Slot,
703    pub(crate) hard_forks: HardForks,
704    pub(crate) transaction_count: u64,
705    pub(crate) tick_height: u64,
706    pub(crate) signature_count: u64,
707    pub(crate) capitalization: u64,
708    pub(crate) max_tick_height: u64,
709    pub(crate) hashes_per_tick: Option<u64>,
710    pub(crate) ticks_per_slot: u64,
711    pub(crate) ns_per_slot: u128,
712    pub(crate) genesis_creation_time: UnixTimestamp,
713    pub(crate) slots_per_year: f64,
714    pub(crate) slot: Slot,
715    pub(crate) epoch: Epoch,
716    pub(crate) block_height: u64,
717    pub(crate) collector_id: Pubkey,
718    pub(crate) collector_fees: u64,
719    pub(crate) fee_calculator: FeeCalculator,
720    pub(crate) fee_rate_governor: FeeRateGovernor,
721    pub(crate) collected_rent: u64,
722    pub(crate) rent_collector: RentCollector,
723    pub(crate) epoch_schedule: EpochSchedule,
724    pub(crate) inflation: Inflation,
725    pub(crate) stakes: Stakes<Delegation>,
726    pub(crate) epoch_stakes: HashMap<Epoch, EpochStakes>,
727    pub(crate) is_delta: bool,
728    pub(crate) accounts_data_len: u64,
729    pub(crate) incremental_snapshot_persistence: Option<BankIncrementalSnapshotPersistence>,
730    pub(crate) epoch_accounts_hash: Option<Hash>,
731}
732
733// Bank's common fields shared by all supported snapshot versions for serialization.
734// This is separated from BankFieldsToDeserialize to avoid cloning by using refs.
735// So, sync fields with BankFieldsToDeserialize!
736// all members are made public to keep Bank private and to make versioned serializer workable on this
737#[derive(Debug)]
738pub(crate) struct BankFieldsToSerialize<'a> {
739    pub(crate) blockhash_queue: &'a RwLock<BlockhashQueue>,
740    pub(crate) ancestors: &'a AncestorsForSerialization,
741    pub(crate) hash: Hash,
742    pub(crate) parent_hash: Hash,
743    pub(crate) parent_slot: Slot,
744    pub(crate) hard_forks: &'a RwLock<HardForks>,
745    pub(crate) transaction_count: u64,
746    pub(crate) tick_height: u64,
747    pub(crate) signature_count: u64,
748    pub(crate) capitalization: u64,
749    pub(crate) max_tick_height: u64,
750    pub(crate) hashes_per_tick: Option<u64>,
751    pub(crate) ticks_per_slot: u64,
752    pub(crate) ns_per_slot: u128,
753    pub(crate) genesis_creation_time: UnixTimestamp,
754    pub(crate) slots_per_year: f64,
755    pub(crate) slot: Slot,
756    pub(crate) epoch: Epoch,
757    pub(crate) block_height: u64,
758    pub(crate) collector_id: Pubkey,
759    pub(crate) collector_fees: u64,
760    pub(crate) fee_calculator: FeeCalculator,
761    pub(crate) fee_rate_governor: FeeRateGovernor,
762    pub(crate) collected_rent: u64,
763    pub(crate) rent_collector: RentCollector,
764    pub(crate) epoch_schedule: EpochSchedule,
765    pub(crate) inflation: Inflation,
766    pub(crate) stakes: &'a StakesCache,
767    pub(crate) epoch_stakes: &'a HashMap<Epoch, EpochStakes>,
768    pub(crate) is_delta: bool,
769    pub(crate) accounts_data_len: u64,
770}
771
772// Can't derive PartialEq because RwLock doesn't implement PartialEq
773impl PartialEq for Bank {
774    fn eq(&self, other: &Self) -> bool {
775        if std::ptr::eq(self, other) {
776            return true;
777        }
778        let Self {
779            rc: _,
780            status_cache: _,
781            blockhash_queue,
782            ancestors,
783            hash,
784            parent_hash,
785            parent_slot,
786            hard_forks,
787            transaction_count,
788            transaction_error_count: _,
789            transaction_entries_count: _,
790            transactions_per_entry_max: _,
791            tick_height,
792            signature_count,
793            capitalization,
794            max_tick_height,
795            hashes_per_tick,
796            ticks_per_slot,
797            ns_per_slot,
798            genesis_creation_time,
799            slots_per_year,
800            slot,
801            bank_id: _,
802            epoch,
803            block_height,
804            collector_id,
805            collector_fees,
806            fee_calculator,
807            fee_rate_governor,
808            collected_rent,
809            rent_collector,
810            epoch_schedule,
811            inflation,
812            stakes_cache,
813            epoch_stakes,
814            is_delta,
815            // TODO: Confirm if all these fields are intentionally ignored!
816            builtin_programs: _,
817            compute_budget: _,
818            builtin_feature_transitions: _,
819            rewards: _,
820            cluster_type: _,
821            lazy_rent_collection: _,
822            rewards_pool_pubkeys: _,
823            cached_executors: _,
824            transaction_debug_keys: _,
825            transaction_log_collector_config: _,
826            transaction_log_collector: _,
827            feature_set: _,
828            drop_callback: _,
829            freeze_started: _,
830            vote_only_bank: _,
831            cost_tracker: _,
832            rewrites_skipped_this_slot: _,
833            sysvar_cache: _,
834            accounts_data_size_initial: _,
835            accounts_data_size_delta_on_chain: _,
836            accounts_data_size_delta_off_chain: _,
837            fee_structure: _,
838            incremental_snapshot_persistence: _,
839            // Ignore new fields explicitly if they do not impact PartialEq.
840            // Adding ".." will remove compile-time checks that if a new field
841            // is added to the struct, this ParitalEq is accordingly updated.
842        } = self;
843        *blockhash_queue.read().unwrap() == *other.blockhash_queue.read().unwrap()
844            && ancestors == &other.ancestors
845            && *hash.read().unwrap() == *other.hash.read().unwrap()
846            && parent_hash == &other.parent_hash
847            && parent_slot == &other.parent_slot
848            && *hard_forks.read().unwrap() == *other.hard_forks.read().unwrap()
849            && transaction_count.load(Relaxed) == other.transaction_count.load(Relaxed)
850            && tick_height.load(Relaxed) == other.tick_height.load(Relaxed)
851            && signature_count.load(Relaxed) == other.signature_count.load(Relaxed)
852            && capitalization.load(Relaxed) == other.capitalization.load(Relaxed)
853            && max_tick_height == &other.max_tick_height
854            && hashes_per_tick == &other.hashes_per_tick
855            && ticks_per_slot == &other.ticks_per_slot
856            && ns_per_slot == &other.ns_per_slot
857            && genesis_creation_time == &other.genesis_creation_time
858            && slots_per_year == &other.slots_per_year
859            && slot == &other.slot
860            && epoch == &other.epoch
861            && block_height == &other.block_height
862            && collector_id == &other.collector_id
863            && collector_fees.load(Relaxed) == other.collector_fees.load(Relaxed)
864            && fee_calculator == &other.fee_calculator
865            && fee_rate_governor == &other.fee_rate_governor
866            && collected_rent.load(Relaxed) == other.collected_rent.load(Relaxed)
867            && rent_collector == &other.rent_collector
868            && epoch_schedule == &other.epoch_schedule
869            && *inflation.read().unwrap() == *other.inflation.read().unwrap()
870            && *stakes_cache.stakes() == *other.stakes_cache.stakes()
871            && epoch_stakes == &other.epoch_stakes
872            && is_delta.load(Relaxed) == other.is_delta.load(Relaxed)
873    }
874}
875
876#[derive(Debug)]
877pub enum RewardCalculationEvent<'a, 'b> {
878    Staking(&'a Pubkey, &'b InflationPointCalculationEvent),
879}
880
881fn null_tracer() -> Option<impl Fn(&RewardCalculationEvent) + Send + Sync> {
882    None::<fn(&RewardCalculationEvent)>
883}
884
885pub trait DropCallback: fmt::Debug {
886    fn callback(&self, b: &Bank);
887    fn clone_box(&self) -> Box<dyn DropCallback + Send + Sync>;
888}
889
890#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, AbiExample, Clone, Copy)]
891pub struct RewardInfo {
892    pub reward_type: RewardType,
893    pub lamports: i64,          // Reward amount
894    pub post_balance: u64,      // Account balance in lamports after `lamports` was applied
895    pub commission: Option<u8>, // Vote account commission when the reward was credited, only present for voting and staking rewards
896}
897
898#[derive(Debug, Default)]
899pub struct OptionalDropCallback(Option<Box<dyn DropCallback + Send + Sync>>);
900
901#[cfg(RUSTC_WITH_SPECIALIZATION)]
902impl AbiExample for OptionalDropCallback {
903    fn example() -> Self {
904        Self(None)
905    }
906}
907
908#[derive(Debug, Clone, Default)]
909pub struct BuiltinPrograms {
910    pub vec: Vec<BuiltinProgram>,
911}
912
913#[cfg(RUSTC_WITH_SPECIALIZATION)]
914impl AbiExample for BuiltinPrograms {
915    fn example() -> Self {
916        Self::default()
917    }
918}
919
920/// Manager for the state of all accounts and programs after processing its entries.
921/// AbiExample is needed even without Serialize/Deserialize; actual (de-)serialization
922/// are implemented elsewhere for versioning
923#[derive(AbiExample, Debug)]
924pub struct Bank {
925    /// References to accounts, parent and signature status
926    pub rc: BankRc,
927
928    /// A cache of signature statuses
929    pub status_cache: Arc<RwLock<BankStatusCache>>,
930
931    /// FIFO queue of `recent_blockhash` items
932    blockhash_queue: RwLock<BlockhashQueue>,
933
934    /// The set of parents including this bank
935    pub ancestors: Ancestors,
936
937    /// Hash of this Bank's state. Only meaningful after freezing.
938    hash: RwLock<Hash>,
939
940    /// Hash of this Bank's parent's state
941    parent_hash: Hash,
942
943    /// parent's slot
944    parent_slot: Slot,
945
946    /// slots to hard fork at
947    hard_forks: Arc<RwLock<HardForks>>,
948
949    /// The number of transactions processed without error
950    transaction_count: AtomicU64,
951
952    /// The number of transaction errors in this slot
953    transaction_error_count: AtomicU64,
954
955    /// The number of transaction entries in this slot
956    transaction_entries_count: AtomicU64,
957
958    /// The max number of transaction in an entry in this slot
959    transactions_per_entry_max: AtomicU64,
960
961    /// Bank tick height
962    tick_height: AtomicU64,
963
964    /// The number of signatures from valid transactions in this slot
965    signature_count: AtomicU64,
966
967    /// Total capitalization, used to calculate inflation
968    capitalization: AtomicU64,
969
970    // Bank max_tick_height
971    max_tick_height: u64,
972
973    /// The number of hashes in each tick. None value means hashing is disabled.
974    hashes_per_tick: Option<u64>,
975
976    /// The number of ticks in each slot.
977    ticks_per_slot: u64,
978
979    /// length of a slot in ns
980    pub ns_per_slot: u128,
981
982    /// genesis time, used for computed clock
983    genesis_creation_time: UnixTimestamp,
984
985    /// The number of slots per year, used for inflation
986    slots_per_year: f64,
987
988    /// Bank slot (i.e. block)
989    slot: Slot,
990
991    bank_id: BankId,
992
993    /// Bank epoch
994    epoch: Epoch,
995
996    /// Bank block_height
997    block_height: u64,
998
999    /// The pubkey to send transactions fees to.
1000    collector_id: Pubkey,
1001
1002    /// Fees that have been collected
1003    collector_fees: AtomicU64,
1004
1005    /// Deprecated, do not use
1006    /// Latest transaction fees for transactions processed by this bank
1007    pub(crate) fee_calculator: FeeCalculator,
1008
1009    /// Track cluster signature throughput and adjust fee rate
1010    pub(crate) fee_rate_governor: FeeRateGovernor,
1011
1012    /// Rent that has been collected
1013    collected_rent: AtomicU64,
1014
1015    /// latest rent collector, knows the epoch
1016    rent_collector: RentCollector,
1017
1018    /// initialized from genesis
1019    epoch_schedule: EpochSchedule,
1020
1021    /// inflation specs
1022    inflation: Arc<RwLock<Inflation>>,
1023
1024    /// cache of vote_account and stake_account state for this fork
1025    stakes_cache: StakesCache,
1026
1027    /// staked nodes on epoch boundaries, saved off when a bank.slot() is at
1028    ///   a leader schedule calculation boundary
1029    epoch_stakes: HashMap<Epoch, EpochStakes>,
1030
1031    /// A boolean reflecting whether any entries were recorded into the PoH
1032    /// stream for the slot == self.slot
1033    is_delta: AtomicBool,
1034
1035    /// The builtin programs
1036    builtin_programs: BuiltinPrograms,
1037
1038    compute_budget: Option<ComputeBudget>,
1039
1040    /// Dynamic feature transitions for builtin programs
1041    #[allow(clippy::rc_buffer)]
1042    builtin_feature_transitions: Arc<Vec<BuiltinFeatureTransition>>,
1043
1044    /// Protocol-level rewards that were distributed by this bank
1045    pub rewards: RwLock<Vec<(Pubkey, RewardInfo)>>,
1046
1047    pub cluster_type: Option<ClusterType>,
1048
1049    pub lazy_rent_collection: AtomicBool,
1050
1051    // this is temporary field only to remove rewards_pool entirely
1052    pub rewards_pool_pubkeys: Arc<HashSet<Pubkey>>,
1053
1054    /// Cached executors
1055    cached_executors: RwLock<CachedExecutors>,
1056
1057    transaction_debug_keys: Option<Arc<HashSet<Pubkey>>>,
1058
1059    // Global configuration for how transaction logs should be collected across all banks
1060    pub transaction_log_collector_config: Arc<RwLock<TransactionLogCollectorConfig>>,
1061
1062    // Logs from transactions that this Bank executed collected according to the criteria in
1063    // `transaction_log_collector_config`
1064    pub transaction_log_collector: Arc<RwLock<TransactionLogCollector>>,
1065
1066    pub feature_set: Arc<FeatureSet>,
1067
1068    /// callback function only to be called when dropping and should only be called once
1069    pub drop_callback: RwLock<OptionalDropCallback>,
1070
1071    pub freeze_started: AtomicBool,
1072
1073    vote_only_bank: bool,
1074
1075    cost_tracker: RwLock<CostTracker>,
1076
1077    sysvar_cache: RwLock<SysvarCache>,
1078
1079    /// (Pubkey, account Hash) for each account that would have been rewritten in rent collection for this slot
1080    pub rewrites_skipped_this_slot: Rewrites,
1081
1082    /// The initial accounts data size at the start of this Bank, before processing any transactions/etc
1083    accounts_data_size_initial: u64,
1084    /// The change to accounts data size in this Bank, due on-chain events (i.e. transactions)
1085    accounts_data_size_delta_on_chain: AtomicI64,
1086    /// The change to accounts data size in this Bank, due to off-chain events (i.e. rent collection)
1087    accounts_data_size_delta_off_chain: AtomicI64,
1088
1089    /// Transaction fee structure
1090    pub fee_structure: FeeStructure,
1091
1092    pub incremental_snapshot_persistence: Option<BankIncrementalSnapshotPersistence>,
1093}
1094
1095struct VoteWithStakeDelegations {
1096    vote_state: Arc<VoteState>,
1097    vote_account: AccountSharedData,
1098    // TODO: use StakeAccount<Delegation> once the old code is deleted.
1099    delegations: Vec<(Pubkey, StakeAccount<()>)>,
1100}
1101
1102struct LoadVoteAndStakeAccountsResult {
1103    vote_with_stake_delegations_map: DashMap<Pubkey, VoteWithStakeDelegations>,
1104    invalid_stake_keys: DashMap<Pubkey, InvalidCacheEntryReason>,
1105    invalid_vote_keys: DashMap<Pubkey, InvalidCacheEntryReason>,
1106    invalid_cached_vote_accounts: usize,
1107    invalid_cached_stake_accounts: usize,
1108    invalid_cached_stake_accounts_rent_epoch: usize,
1109    vote_accounts_cache_miss_count: usize,
1110}
1111
1112#[derive(Debug, Default)]
1113pub struct NewBankOptions {
1114    pub vote_only_bank: bool,
1115}
1116
1117#[derive(Debug)]
1118struct PrevEpochInflationRewards {
1119    validator_rewards: u64,
1120    prev_epoch_duration_in_years: f64,
1121    validator_rate: f64,
1122    foundation_rate: f64,
1123}
1124
1125pub struct CommitTransactionCounts {
1126    pub committed_transactions_count: u64,
1127    pub committed_with_failure_result_count: u64,
1128    pub signature_count: u64,
1129}
1130
1131struct StakeReward {
1132    stake_pubkey: Pubkey,
1133    stake_reward_info: RewardInfo,
1134    stake_account: AccountSharedData,
1135}
1136
1137impl StakeReward {
1138    pub fn get_stake_reward(&self) -> i64 {
1139        self.stake_reward_info.lamports
1140    }
1141}
1142
1143/// allow [StakeReward] to be passed to `StoreAccounts` directly without copies or vec construction
1144impl<'a> StorableAccounts<'a, AccountSharedData> for (Slot, &'a [StakeReward]) {
1145    fn pubkey(&self, index: usize) -> &Pubkey {
1146        &self.1[index].stake_pubkey
1147    }
1148    fn account(&self, index: usize) -> &AccountSharedData {
1149        &self.1[index].stake_account
1150    }
1151    fn slot(&self, _index: usize) -> Slot {
1152        // per-index slot is not unique per slot when per-account slot is not included in the source data
1153        self.target_slot()
1154    }
1155    fn target_slot(&self) -> Slot {
1156        self.0
1157    }
1158    fn len(&self) -> usize {
1159        self.1.len()
1160    }
1161    fn contains_multiple_slots(&self) -> bool {
1162        false
1163    }
1164}
1165
1166impl Bank {
1167    pub fn default_for_tests() -> Self {
1168        Self::default_with_accounts(Accounts::default_for_tests())
1169    }
1170
1171    pub fn new_for_benches(genesis_config: &GenesisConfig) -> Self {
1172        Self::new_with_paths_for_benches(
1173            genesis_config,
1174            Vec::new(),
1175            None,
1176            None,
1177            AccountSecondaryIndexes::default(),
1178            false,
1179            AccountShrinkThreshold::default(),
1180            false,
1181        )
1182    }
1183
1184    pub fn new_for_tests(genesis_config: &GenesisConfig) -> Self {
1185        Self::new_with_config_for_tests(
1186            genesis_config,
1187            AccountSecondaryIndexes::default(),
1188            false,
1189            AccountShrinkThreshold::default(),
1190        )
1191    }
1192
1193    pub fn new_no_wallclock_throttle_for_tests(genesis_config: &GenesisConfig) -> Self {
1194        let mut bank = Self::new_for_tests(genesis_config);
1195
1196        bank.ns_per_slot = std::u128::MAX;
1197        bank
1198    }
1199
1200    pub(crate) fn new_with_config_for_tests(
1201        genesis_config: &GenesisConfig,
1202        account_indexes: AccountSecondaryIndexes,
1203        accounts_db_caching_enabled: bool,
1204        shrink_ratio: AccountShrinkThreshold,
1205    ) -> Self {
1206        Self::new_with_paths_for_tests(
1207            genesis_config,
1208            Vec::new(),
1209            None,
1210            None,
1211            account_indexes,
1212            accounts_db_caching_enabled,
1213            shrink_ratio,
1214            false,
1215            None,
1216        )
1217    }
1218
1219    fn default_with_accounts(accounts: Accounts) -> Self {
1220        let mut bank = Self {
1221            incremental_snapshot_persistence: None,
1222            rewrites_skipped_this_slot: Rewrites::default(),
1223            rc: BankRc::new(accounts, Slot::default()),
1224            status_cache: Arc::<RwLock<BankStatusCache>>::default(),
1225            blockhash_queue: RwLock::<BlockhashQueue>::default(),
1226            ancestors: Ancestors::default(),
1227            hash: RwLock::<Hash>::default(),
1228            parent_hash: Hash::default(),
1229            parent_slot: Slot::default(),
1230            hard_forks: Arc::<RwLock<HardForks>>::default(),
1231            transaction_count: AtomicU64::default(),
1232            transaction_error_count: AtomicU64::default(),
1233            transaction_entries_count: AtomicU64::default(),
1234            transactions_per_entry_max: AtomicU64::default(),
1235            tick_height: AtomicU64::default(),
1236            signature_count: AtomicU64::default(),
1237            capitalization: AtomicU64::default(),
1238            max_tick_height: u64::default(),
1239            hashes_per_tick: Option::<u64>::default(),
1240            ticks_per_slot: u64::default(),
1241            ns_per_slot: u128::default(),
1242            genesis_creation_time: UnixTimestamp::default(),
1243            slots_per_year: f64::default(),
1244            slot: Slot::default(),
1245            bank_id: BankId::default(),
1246            epoch: Epoch::default(),
1247            block_height: u64::default(),
1248            collector_id: Pubkey::default(),
1249            collector_fees: AtomicU64::default(),
1250            fee_calculator: FeeCalculator::default(),
1251            fee_rate_governor: FeeRateGovernor::default(),
1252            collected_rent: AtomicU64::default(),
1253            rent_collector: RentCollector::default(),
1254            epoch_schedule: EpochSchedule::default(),
1255            inflation: Arc::<RwLock<Inflation>>::default(),
1256            stakes_cache: StakesCache::default(),
1257            epoch_stakes: HashMap::<Epoch, EpochStakes>::default(),
1258            is_delta: AtomicBool::default(),
1259            builtin_programs: BuiltinPrograms::default(),
1260            compute_budget: Option::<ComputeBudget>::default(),
1261            builtin_feature_transitions: Arc::<Vec<BuiltinFeatureTransition>>::default(),
1262            rewards: RwLock::<Vec<(Pubkey, RewardInfo)>>::default(),
1263            cluster_type: Option::<ClusterType>::default(),
1264            lazy_rent_collection: AtomicBool::default(),
1265            rewards_pool_pubkeys: Arc::<HashSet<Pubkey>>::default(),
1266            cached_executors: RwLock::<CachedExecutors>::default(),
1267            transaction_debug_keys: Option::<Arc<HashSet<Pubkey>>>::default(),
1268            transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
1269            ),
1270            transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
1271            feature_set: Arc::<FeatureSet>::default(),
1272            drop_callback: RwLock::new(OptionalDropCallback(None)),
1273            freeze_started: AtomicBool::default(),
1274            vote_only_bank: false,
1275            cost_tracker: RwLock::<CostTracker>::default(),
1276            sysvar_cache: RwLock::<SysvarCache>::default(),
1277            accounts_data_size_initial: 0,
1278            accounts_data_size_delta_on_chain: AtomicI64::new(0),
1279            accounts_data_size_delta_off_chain: AtomicI64::new(0),
1280            fee_structure: FeeStructure::default(),
1281        };
1282
1283        let accounts_data_size_initial = bank.get_total_accounts_stats().unwrap().data_len as u64;
1284        bank.accounts_data_size_initial = accounts_data_size_initial;
1285
1286        bank
1287    }
1288
1289    pub fn new_with_paths_for_tests(
1290        genesis_config: &GenesisConfig,
1291        paths: Vec<PathBuf>,
1292        debug_keys: Option<Arc<HashSet<Pubkey>>>,
1293        additional_builtins: Option<&Builtins>,
1294        account_indexes: AccountSecondaryIndexes,
1295        accounts_db_caching_enabled: bool,
1296        shrink_ratio: AccountShrinkThreshold,
1297        debug_do_not_add_builtins: bool,
1298        accounts_db_config: Option<AccountsDbConfig>,
1299    ) -> Self {
1300        Self::new_with_paths(
1301            genesis_config,
1302            paths,
1303            debug_keys,
1304            additional_builtins,
1305            account_indexes,
1306            accounts_db_caching_enabled,
1307            shrink_ratio,
1308            debug_do_not_add_builtins,
1309            accounts_db_config.or(Some(ACCOUNTS_DB_CONFIG_FOR_TESTING)),
1310            None,
1311        )
1312    }
1313
1314    pub fn new_with_paths_for_benches(
1315        genesis_config: &GenesisConfig,
1316        paths: Vec<PathBuf>,
1317        debug_keys: Option<Arc<HashSet<Pubkey>>>,
1318        additional_builtins: Option<&Builtins>,
1319        account_indexes: AccountSecondaryIndexes,
1320        accounts_db_caching_enabled: bool,
1321        shrink_ratio: AccountShrinkThreshold,
1322        debug_do_not_add_builtins: bool,
1323    ) -> Self {
1324        Self::new_with_paths(
1325            genesis_config,
1326            paths,
1327            debug_keys,
1328            additional_builtins,
1329            account_indexes,
1330            accounts_db_caching_enabled,
1331            shrink_ratio,
1332            debug_do_not_add_builtins,
1333            Some(ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS),
1334            None,
1335        )
1336    }
1337
1338    #[allow(clippy::too_many_arguments)]
1339    pub fn new_with_paths(
1340        genesis_config: &GenesisConfig,
1341        paths: Vec<PathBuf>,
1342        debug_keys: Option<Arc<HashSet<Pubkey>>>,
1343        additional_builtins: Option<&Builtins>,
1344        account_indexes: AccountSecondaryIndexes,
1345        accounts_db_caching_enabled: bool,
1346        shrink_ratio: AccountShrinkThreshold,
1347        debug_do_not_add_builtins: bool,
1348        accounts_db_config: Option<AccountsDbConfig>,
1349        accounts_update_notifier: Option<AccountsUpdateNotifier>,
1350    ) -> Self {
1351        let accounts = Accounts::new_with_config(
1352            paths,
1353            &genesis_config.cluster_type,
1354            account_indexes,
1355            accounts_db_caching_enabled,
1356            shrink_ratio,
1357            accounts_db_config,
1358            accounts_update_notifier,
1359        );
1360        let mut bank = Self::default_with_accounts(accounts);
1361        bank.ancestors = Ancestors::from(vec![bank.slot()]);
1362        bank.transaction_debug_keys = debug_keys;
1363        bank.cluster_type = Some(genesis_config.cluster_type);
1364
1365        bank.process_genesis_config(genesis_config);
1366        bank.finish_init(
1367            genesis_config,
1368            additional_builtins,
1369            debug_do_not_add_builtins,
1370        );
1371
1372        // genesis needs stakes for all epochs up to the epoch implied by
1373        //  slot = 0 and genesis configuration
1374        {
1375            let stakes = bank.stakes_cache.stakes().clone();
1376            let stakes = Arc::new(StakesEnum::from(stakes));
1377            for epoch in 0..=bank.get_leader_schedule_epoch(bank.slot) {
1378                bank.epoch_stakes
1379                    .insert(epoch, EpochStakes::new(stakes.clone(), epoch));
1380            }
1381            bank.update_stake_history(None);
1382        }
1383        bank.update_clock(None);
1384        bank.update_rent();
1385        bank.update_epoch_schedule();
1386        bank.update_recent_blockhashes();
1387        bank.fill_missing_sysvar_cache_entries();
1388        bank
1389    }
1390
1391    /// Create a new bank that points to an immutable checkpoint of another bank.
1392    pub fn new_from_parent(parent: &Arc<Bank>, collector_id: &Pubkey, slot: Slot) -> Self {
1393        Self::_new_from_parent(
1394            parent,
1395            collector_id,
1396            slot,
1397            null_tracer(),
1398            NewBankOptions::default(),
1399        )
1400    }
1401
1402    pub fn new_from_parent_with_options(
1403        parent: &Arc<Bank>,
1404        collector_id: &Pubkey,
1405        slot: Slot,
1406        new_bank_options: NewBankOptions,
1407    ) -> Self {
1408        Self::_new_from_parent(parent, collector_id, slot, null_tracer(), new_bank_options)
1409    }
1410
1411    pub fn new_from_parent_with_tracer(
1412        parent: &Arc<Bank>,
1413        collector_id: &Pubkey,
1414        slot: Slot,
1415        reward_calc_tracer: impl Fn(&RewardCalculationEvent) + Send + Sync,
1416    ) -> Self {
1417        Self::_new_from_parent(
1418            parent,
1419            collector_id,
1420            slot,
1421            Some(reward_calc_tracer),
1422            NewBankOptions::default(),
1423        )
1424    }
1425
1426    fn get_rent_collector_from(rent_collector: &RentCollector, epoch: Epoch) -> RentCollector {
1427        rent_collector.clone_with_epoch(epoch)
1428    }
1429
1430    fn _new_from_parent(
1431        parent: &Arc<Bank>,
1432        collector_id: &Pubkey,
1433        slot: Slot,
1434        reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
1435        new_bank_options: NewBankOptions,
1436    ) -> Self {
1437        let mut time = Measure::start("bank::new_from_parent");
1438        let NewBankOptions { vote_only_bank } = new_bank_options;
1439
1440        parent.freeze();
1441        assert_ne!(slot, parent.slot());
1442
1443        let epoch_schedule = parent.epoch_schedule;
1444        let epoch = epoch_schedule.get_epoch(slot);
1445
1446        let (rc, bank_rc_time) = measure!(
1447            BankRc {
1448                accounts: Arc::new(Accounts::new_from_parent(
1449                    &parent.rc.accounts,
1450                    slot,
1451                    parent.slot(),
1452                )),
1453                parent: RwLock::new(Some(parent.clone())),
1454                slot,
1455                bank_id_generator: parent.rc.bank_id_generator.clone(),
1456            },
1457            "bank_rc_creation",
1458        );
1459
1460        let (status_cache, status_cache_time) =
1461            measure!(Arc::clone(&parent.status_cache), "status_cache_creation",);
1462
1463        let ((fee_rate_governor, fee_calculator), fee_components_time) = measure!(
1464            {
1465                let fee_rate_governor = FeeRateGovernor::new_derived(
1466                    &parent.fee_rate_governor,
1467                    parent.signature_count(),
1468                );
1469
1470                let fee_calculator = if parent.feature_set.is_active(&disable_fee_calculator::id())
1471                {
1472                    FeeCalculator::default()
1473                } else {
1474                    fee_rate_governor.create_fee_calculator()
1475                };
1476                (fee_rate_governor, fee_calculator)
1477            },
1478            "fee_components_creation",
1479        );
1480
1481        let bank_id = rc.bank_id_generator.fetch_add(1, Relaxed) + 1;
1482        let (blockhash_queue, blockhash_queue_time) = measure!(
1483            RwLock::new(parent.blockhash_queue.read().unwrap().clone()),
1484            "blockhash_queue_creation",
1485        );
1486
1487        let (stakes_cache, stakes_cache_time) = measure!(
1488            StakesCache::new(parent.stakes_cache.stakes().clone()),
1489            "stakes_cache_creation",
1490        );
1491
1492        let (epoch_stakes, epoch_stakes_time) =
1493            measure!(parent.epoch_stakes.clone(), "epoch_stakes_creation");
1494
1495        let (builtin_programs, builtin_programs_time) =
1496            measure!(parent.builtin_programs.clone(), "builtin_programs_creation");
1497
1498        let (rewards_pool_pubkeys, rewards_pool_pubkeys_time) = measure!(
1499            parent.rewards_pool_pubkeys.clone(),
1500            "rewards_pool_pubkeys_creation",
1501        );
1502
1503        let (cached_executors, cached_executors_time) = measure!(
1504            {
1505                let parent_bank_executors = parent.cached_executors.read().unwrap();
1506                RwLock::new(CachedExecutors::new_from_parent_bank_executors(
1507                    &parent_bank_executors,
1508                    epoch,
1509                ))
1510            },
1511            "cached_executors_creation",
1512        );
1513
1514        let (transaction_debug_keys, transaction_debug_keys_time) = measure!(
1515            parent.transaction_debug_keys.clone(),
1516            "transation_debug_keys_creation",
1517        );
1518
1519        let (transaction_log_collector_config, transaction_log_collector_config_time) = measure!(
1520            parent.transaction_log_collector_config.clone(),
1521            "transaction_log_collector_config_creation",
1522        );
1523
1524        let (feature_set, feature_set_time) =
1525            measure!(parent.feature_set.clone(), "feature_set_creation");
1526
1527        let accounts_data_size_initial = parent.load_accounts_data_size();
1528        let mut new = Bank {
1529            incremental_snapshot_persistence: None,
1530            rewrites_skipped_this_slot: Rewrites::default(),
1531            rc,
1532            status_cache,
1533            slot,
1534            bank_id,
1535            epoch,
1536            blockhash_queue,
1537
1538            // TODO: clean this up, so much special-case copying...
1539            hashes_per_tick: parent.hashes_per_tick,
1540            ticks_per_slot: parent.ticks_per_slot,
1541            ns_per_slot: parent.ns_per_slot,
1542            genesis_creation_time: parent.genesis_creation_time,
1543            slots_per_year: parent.slots_per_year,
1544            epoch_schedule,
1545            collected_rent: AtomicU64::new(0),
1546            rent_collector: Self::get_rent_collector_from(&parent.rent_collector, epoch),
1547            max_tick_height: (slot + 1) * parent.ticks_per_slot,
1548            block_height: parent.block_height + 1,
1549            fee_calculator,
1550            fee_rate_governor,
1551            capitalization: AtomicU64::new(parent.capitalization()),
1552            vote_only_bank,
1553            inflation: parent.inflation.clone(),
1554            transaction_count: AtomicU64::new(parent.transaction_count()),
1555            transaction_error_count: AtomicU64::new(0),
1556            transaction_entries_count: AtomicU64::new(0),
1557            transactions_per_entry_max: AtomicU64::new(0),
1558            // we will .clone_with_epoch() this soon after stake data update; so just .clone() for now
1559            stakes_cache,
1560            epoch_stakes,
1561            parent_hash: parent.hash(),
1562            parent_slot: parent.slot(),
1563            collector_id: *collector_id,
1564            collector_fees: AtomicU64::new(0),
1565            ancestors: Ancestors::default(),
1566            hash: RwLock::new(Hash::default()),
1567            is_delta: AtomicBool::new(false),
1568            tick_height: AtomicU64::new(parent.tick_height.load(Relaxed)),
1569            signature_count: AtomicU64::new(0),
1570            builtin_programs,
1571            compute_budget: parent.compute_budget,
1572            builtin_feature_transitions: parent.builtin_feature_transitions.clone(),
1573            hard_forks: parent.hard_forks.clone(),
1574            rewards: RwLock::new(vec![]),
1575            cluster_type: parent.cluster_type,
1576            lazy_rent_collection: AtomicBool::new(parent.lazy_rent_collection.load(Relaxed)),
1577            rewards_pool_pubkeys,
1578            cached_executors,
1579            transaction_debug_keys,
1580            transaction_log_collector_config,
1581            transaction_log_collector: Arc::new(RwLock::new(TransactionLogCollector::default())),
1582            feature_set: Arc::clone(&feature_set),
1583            drop_callback: RwLock::new(OptionalDropCallback(
1584                parent
1585                    .drop_callback
1586                    .read()
1587                    .unwrap()
1588                    .0
1589                    .as_ref()
1590                    .map(|drop_callback| drop_callback.clone_box()),
1591            )),
1592            freeze_started: AtomicBool::new(false),
1593            cost_tracker: RwLock::new(CostTracker::new_with_account_data_size_limit(
1594                feature_set
1595                    .is_active(&feature_set::cap_accounts_data_len::id())
1596                    .then(|| {
1597                        parent
1598                            .accounts_data_size_limit()
1599                            .saturating_sub(accounts_data_size_initial)
1600                    }),
1601            )),
1602            sysvar_cache: RwLock::new(SysvarCache::default()),
1603            accounts_data_size_initial,
1604            accounts_data_size_delta_on_chain: AtomicI64::new(0),
1605            accounts_data_size_delta_off_chain: AtomicI64::new(0),
1606            fee_structure: parent.fee_structure.clone(),
1607        };
1608
1609        let (_, ancestors_time) = measure!(
1610            {
1611                let mut ancestors = Vec::with_capacity(1 + new.parents().len());
1612                ancestors.push(new.slot());
1613                new.parents().iter().for_each(|p| {
1614                    ancestors.push(p.slot());
1615                });
1616                new.ancestors = Ancestors::from(ancestors);
1617            },
1618            "ancestors_creation",
1619        );
1620
1621        // Following code may touch AccountsDb, requiring proper ancestors
1622        let parent_epoch = parent.epoch();
1623        let (_, update_epoch_time) = measure!(
1624            {
1625                if parent_epoch < new.epoch() {
1626                    let (thread_pool, thread_pool_time) = measure!(
1627                        ThreadPoolBuilder::new().build().unwrap(),
1628                        "thread_pool_creation",
1629                    );
1630
1631                    let (_, apply_feature_activations_time) = measure!(
1632                        new.apply_feature_activations(
1633                            ApplyFeatureActivationsCaller::NewFromParent,
1634                            false
1635                        ),
1636                        "apply_feature_activation",
1637                    );
1638
1639                    // Add new entry to stakes.stake_history, set appropriate epoch and
1640                    // update vote accounts with warmed up stakes before saving a
1641                    // snapshot of stakes in epoch stakes
1642                    let (_, activate_epoch_time) = measure!(
1643                        new.stakes_cache.activate_epoch(epoch, &thread_pool),
1644                        "activate_epoch",
1645                    );
1646
1647                    // Save a snapshot of stakes for use in consensus and stake weighted networking
1648                    let leader_schedule_epoch = epoch_schedule.get_leader_schedule_epoch(slot);
1649                    let (_, update_epoch_stakes_time) = measure!(
1650                        new.update_epoch_stakes(leader_schedule_epoch),
1651                        "update_epoch_stakes",
1652                    );
1653
1654                    let mut metrics = RewardsMetrics::default();
1655                    // After saving a snapshot of stakes, apply stake rewards and commission
1656                    let (_, update_rewards_with_thread_pool_time) = measure!(
1657                        {
1658                            new.update_rewards_with_thread_pool(
1659                                parent_epoch,
1660                                reward_calc_tracer,
1661                                &thread_pool,
1662                                &mut metrics,
1663                            )
1664                        },
1665                        "update_rewards_with_thread_pool",
1666                    );
1667
1668                    datapoint_info!(
1669                        "bank-new_from_parent-new_epoch_timings",
1670                        ("epoch", new.epoch(), i64),
1671                        ("slot", slot, i64),
1672                        ("parent_slot", parent.slot(), i64),
1673                        ("thread_pool_creation_us", thread_pool_time.as_us(), i64),
1674                        (
1675                            "apply_feature_activations",
1676                            apply_feature_activations_time.as_us(),
1677                            i64
1678                        ),
1679                        ("activate_epoch_us", activate_epoch_time.as_us(), i64),
1680                        (
1681                            "update_epoch_stakes_us",
1682                            update_epoch_stakes_time.as_us(),
1683                            i64
1684                        ),
1685                        (
1686                            "update_rewards_with_thread_pool_us",
1687                            update_rewards_with_thread_pool_time.as_us(),
1688                            i64
1689                        ),
1690                        (
1691                            "load_vote_and_stake_accounts_us",
1692                            metrics.load_vote_and_stake_accounts_us.load(Relaxed),
1693                            i64
1694                        ),
1695                        (
1696                            "calculate_points_us",
1697                            metrics.calculate_points_us.load(Relaxed),
1698                            i64
1699                        ),
1700                        ("redeem_rewards_us", metrics.redeem_rewards_us, i64),
1701                        (
1702                            "store_stake_accounts_us",
1703                            metrics.store_stake_accounts_us.load(Relaxed),
1704                            i64
1705                        ),
1706                        (
1707                            "store_vote_accounts_us",
1708                            metrics.store_vote_accounts_us.load(Relaxed),
1709                            i64
1710                        ),
1711                        (
1712                            "invalid_cached_vote_accounts",
1713                            metrics.invalid_cached_vote_accounts,
1714                            i64
1715                        ),
1716                        (
1717                            "invalid_cached_stake_accounts",
1718                            metrics.invalid_cached_stake_accounts,
1719                            i64
1720                        ),
1721                        (
1722                            "invalid_cached_stake_accounts_rent_epoch",
1723                            metrics.invalid_cached_stake_accounts_rent_epoch,
1724                            i64
1725                        ),
1726                        (
1727                            "vote_accounts_cache_miss_count",
1728                            metrics.vote_accounts_cache_miss_count,
1729                            i64
1730                        ),
1731                    );
1732                } else {
1733                    // Save a snapshot of stakes for use in consensus and stake weighted networking
1734                    let leader_schedule_epoch = epoch_schedule.get_leader_schedule_epoch(slot);
1735                    new.update_epoch_stakes(leader_schedule_epoch);
1736                }
1737            },
1738            "update_epoch",
1739        );
1740
1741        // Update sysvars before processing transactions
1742        let (_, update_sysvars_time) = measure!(
1743            {
1744                new.update_slot_hashes();
1745                new.update_stake_history(Some(parent_epoch));
1746                new.update_clock(Some(parent_epoch));
1747                new.update_fees();
1748            },
1749            "update_sysvars",
1750        );
1751
1752        let (_, fill_sysvar_cache_time) =
1753            measure!(new.fill_missing_sysvar_cache_entries(), "fill_sysvar_cache");
1754
1755        time.stop();
1756
1757        datapoint_info!(
1758            "bank-new_from_parent-heights",
1759            ("slot", slot, i64),
1760            ("block_height", new.block_height, i64),
1761            ("parent_slot", parent.slot(), i64),
1762            ("bank_rc_creation_us", bank_rc_time.as_us(), i64),
1763            ("total_elapsed_us", time.as_us(), i64),
1764            ("status_cache_us", status_cache_time.as_us(), i64),
1765            ("fee_components_us", fee_components_time.as_us(), i64),
1766            ("blockhash_queue_us", blockhash_queue_time.as_us(), i64),
1767            ("stakes_cache_us", stakes_cache_time.as_us(), i64),
1768            ("epoch_stakes_time_us", epoch_stakes_time.as_us(), i64),
1769            ("builtin_programs_us", builtin_programs_time.as_us(), i64),
1770            (
1771                "rewards_pool_pubkeys_us",
1772                rewards_pool_pubkeys_time.as_us(),
1773                i64
1774            ),
1775            ("cached_executors_us", cached_executors_time.as_us(), i64),
1776            (
1777                "transaction_debug_keys_us",
1778                transaction_debug_keys_time.as_us(),
1779                i64
1780            ),
1781            (
1782                "transaction_log_collector_config_us",
1783                transaction_log_collector_config_time.as_us(),
1784                i64
1785            ),
1786            ("feature_set_us", feature_set_time.as_us(), i64),
1787            ("ancestors_us", ancestors_time.as_us(), i64),
1788            ("update_epoch_us", update_epoch_time.as_us(), i64),
1789            ("update_sysvars_us", update_sysvars_time.as_us(), i64),
1790            ("fill_sysvar_cache_us", fill_sysvar_cache_time.as_us(), i64),
1791        );
1792
1793        parent
1794            .cached_executors
1795            .read()
1796            .unwrap()
1797            .stats
1798            .submit(parent.slot());
1799
1800        new
1801    }
1802
1803    pub fn byte_limit_for_scans(&self) -> Option<usize> {
1804        self.rc
1805            .accounts
1806            .accounts_db
1807            .accounts_index
1808            .scan_results_limit_bytes
1809    }
1810
1811    pub fn proper_ancestors_set(&self) -> HashSet<Slot> {
1812        HashSet::from_iter(self.proper_ancestors())
1813    }
1814
1815    /// Returns all ancestors excluding self.slot.
1816    pub(crate) fn proper_ancestors(&self) -> impl Iterator<Item = Slot> + '_ {
1817        self.ancestors
1818            .keys()
1819            .into_iter()
1820            .filter(move |slot| *slot != self.slot)
1821    }
1822
1823    pub fn set_callback(&self, callback: Option<Box<dyn DropCallback + Send + Sync>>) {
1824        *self.drop_callback.write().unwrap() = OptionalDropCallback(callback);
1825    }
1826
1827    pub fn vote_only_bank(&self) -> bool {
1828        self.vote_only_bank
1829    }
1830
1831    /// Like `new_from_parent` but additionally:
1832    /// * Doesn't assume that the parent is anywhere near `slot`, parent could be millions of slots
1833    /// in the past
1834    /// * Adjusts the new bank's tick height to avoid having to run PoH for millions of slots
1835    /// * Freezes the new bank, assuming that the user will `Bank::new_from_parent` from this bank
1836    pub fn warp_from_parent(parent: &Arc<Bank>, collector_id: &Pubkey, slot: Slot) -> Self {
1837        let parent_timestamp = parent.clock().unix_timestamp;
1838        let mut new = Bank::new_from_parent(parent, collector_id, slot);
1839        new.apply_feature_activations(ApplyFeatureActivationsCaller::WarpFromParent, false);
1840        new.update_epoch_stakes(new.epoch_schedule().get_epoch(slot));
1841        new.tick_height.store(new.max_tick_height(), Relaxed);
1842
1843        let mut clock = new.clock();
1844        clock.epoch_start_timestamp = parent_timestamp;
1845        clock.unix_timestamp = parent_timestamp;
1846        new.update_sysvar_account(&sysvar::clock::id(), |account| {
1847            create_account(
1848                &clock,
1849                new.inherit_specially_retained_account_fields(account),
1850            )
1851        });
1852        new.fill_missing_sysvar_cache_entries();
1853        new.freeze();
1854        new
1855    }
1856
1857    /// Create a bank from explicit arguments and deserialized fields from snapshot
1858    #[allow(clippy::float_cmp)]
1859    pub(crate) fn new_from_fields(
1860        bank_rc: BankRc,
1861        genesis_config: &GenesisConfig,
1862        fields: BankFieldsToDeserialize,
1863        debug_keys: Option<Arc<HashSet<Pubkey>>>,
1864        additional_builtins: Option<&Builtins>,
1865        debug_do_not_add_builtins: bool,
1866        accounts_data_size_initial: u64,
1867    ) -> Self {
1868        let now = Instant::now();
1869        let ancestors = Ancestors::from(&fields.ancestors);
1870        // For backward compatibility, we can only serialize and deserialize
1871        // Stakes<Delegation> in BankFieldsTo{Serialize,Deserialize}. But Bank
1872        // caches Stakes<StakeAccount>. Below Stakes<StakeAccount> is obtained
1873        // from Stakes<Delegation> by reading the full account state from
1874        // accounts-db. Note that it is crucial that these accounts are loaded
1875        // at the right slot and match precisely with serialized Delegations.
1876        let stakes = Stakes::new(&fields.stakes, |pubkey| {
1877            let (account, _slot) = bank_rc.accounts.load_with_fixed_root(&ancestors, pubkey)?;
1878            Some(account)
1879        })
1880        .expect(
1881            "Stakes cache is inconsistent with accounts-db. This can indicate \
1882            a corrupted snapshot or bugs in cached accounts or accounts-db.",
1883        );
1884        let stakes_accounts_load_duration = now.elapsed();
1885        fn new<T: Default>() -> T {
1886            T::default()
1887        }
1888        let feature_set = new();
1889        let mut bank = Self {
1890            incremental_snapshot_persistence: fields.incremental_snapshot_persistence,
1891            rewrites_skipped_this_slot: Rewrites::default(),
1892            rc: bank_rc,
1893            status_cache: new(),
1894            blockhash_queue: RwLock::new(fields.blockhash_queue),
1895            ancestors,
1896            hash: RwLock::new(fields.hash),
1897            parent_hash: fields.parent_hash,
1898            parent_slot: fields.parent_slot,
1899            hard_forks: Arc::new(RwLock::new(fields.hard_forks)),
1900            transaction_count: AtomicU64::new(fields.transaction_count),
1901            transaction_error_count: new(),
1902            transaction_entries_count: new(),
1903            transactions_per_entry_max: new(),
1904            tick_height: AtomicU64::new(fields.tick_height),
1905            signature_count: AtomicU64::new(fields.signature_count),
1906            capitalization: AtomicU64::new(fields.capitalization),
1907            max_tick_height: fields.max_tick_height,
1908            hashes_per_tick: fields.hashes_per_tick,
1909            ticks_per_slot: fields.ticks_per_slot,
1910            ns_per_slot: fields.ns_per_slot,
1911            genesis_creation_time: fields.genesis_creation_time,
1912            slots_per_year: fields.slots_per_year,
1913            slot: fields.slot,
1914            bank_id: 0,
1915            epoch: fields.epoch,
1916            block_height: fields.block_height,
1917            collector_id: fields.collector_id,
1918            collector_fees: AtomicU64::new(fields.collector_fees),
1919            fee_calculator: fields.fee_calculator,
1920            fee_rate_governor: fields.fee_rate_governor,
1921            collected_rent: AtomicU64::new(fields.collected_rent),
1922            // clone()-ing is needed to consider a gated behavior in rent_collector
1923            rent_collector: Self::get_rent_collector_from(&fields.rent_collector, fields.epoch),
1924            epoch_schedule: fields.epoch_schedule,
1925            inflation: Arc::new(RwLock::new(fields.inflation)),
1926            stakes_cache: StakesCache::new(stakes),
1927            epoch_stakes: fields.epoch_stakes,
1928            is_delta: AtomicBool::new(fields.is_delta),
1929            builtin_programs: new(),
1930            compute_budget: None,
1931            builtin_feature_transitions: new(),
1932            rewards: new(),
1933            cluster_type: Some(genesis_config.cluster_type),
1934            lazy_rent_collection: new(),
1935            rewards_pool_pubkeys: new(),
1936            cached_executors: RwLock::new(CachedExecutors::new(MAX_CACHED_EXECUTORS, fields.epoch)),
1937            transaction_debug_keys: debug_keys,
1938            transaction_log_collector_config: new(),
1939            transaction_log_collector: new(),
1940            feature_set: Arc::clone(&feature_set),
1941            drop_callback: RwLock::new(OptionalDropCallback(None)),
1942            freeze_started: AtomicBool::new(fields.hash != Hash::default()),
1943            vote_only_bank: false,
1944            cost_tracker: RwLock::new(CostTracker::default()),
1945            sysvar_cache: RwLock::new(SysvarCache::default()),
1946            accounts_data_size_initial,
1947            accounts_data_size_delta_on_chain: AtomicI64::new(0),
1948            accounts_data_size_delta_off_chain: AtomicI64::new(0),
1949            fee_structure: FeeStructure::default(),
1950        };
1951        bank.finish_init(
1952            genesis_config,
1953            additional_builtins,
1954            debug_do_not_add_builtins,
1955        );
1956
1957        // Sanity assertions between bank snapshot and genesis config
1958        // Consider removing from serializable bank state
1959        // (BankFieldsToSerialize/BankFieldsToDeserialize) and initializing
1960        // from the passed in genesis_config instead (as new()/new_with_paths() already do)
1961        assert_eq!(
1962            bank.genesis_creation_time, genesis_config.creation_time,
1963            "Bank snapshot genesis creation time does not match genesis.bin creation time.\
1964             The snapshot and genesis.bin might pertain to different clusters"
1965        );
1966        assert_eq!(
1967            bank.hashes_per_tick,
1968            genesis_config.poh_config.hashes_per_tick
1969        );
1970        assert_eq!(bank.ticks_per_slot, genesis_config.ticks_per_slot);
1971        assert_eq!(
1972            bank.ns_per_slot,
1973            genesis_config.poh_config.target_tick_duration.as_nanos()
1974                * genesis_config.ticks_per_slot as u128
1975        );
1976        assert_eq!(bank.max_tick_height, (bank.slot + 1) * bank.ticks_per_slot);
1977        assert_eq!(
1978            bank.slots_per_year,
1979            years_as_slots(
1980                1.0,
1981                &genesis_config.poh_config.target_tick_duration,
1982                bank.ticks_per_slot,
1983            )
1984        );
1985        assert_eq!(bank.epoch_schedule, genesis_config.epoch_schedule);
1986        assert_eq!(bank.epoch, bank.epoch_schedule.get_epoch(bank.slot));
1987        if !bank.feature_set.is_active(&disable_fee_calculator::id()) {
1988            bank.fee_rate_governor.lamports_per_signature =
1989                bank.fee_calculator.lamports_per_signature;
1990            assert_eq!(
1991                bank.fee_rate_governor.create_fee_calculator(),
1992                bank.fee_calculator
1993            );
1994        }
1995
1996        datapoint_info!(
1997            "bank-new-from-fields",
1998            (
1999                "accounts_data_len-from-snapshot",
2000                fields.accounts_data_len as i64,
2001                i64
2002            ),
2003            (
2004                "accounts_data_len-from-generate_index",
2005                accounts_data_size_initial as i64,
2006                i64
2007            ),
2008            (
2009                "stakes_accounts_load_duration_us",
2010                stakes_accounts_load_duration.as_micros(),
2011                i64
2012            ),
2013        );
2014        bank
2015    }
2016
2017    /// Return subset of bank fields representing serializable state
2018    pub(crate) fn get_fields_to_serialize<'a>(
2019        &'a self,
2020        ancestors: &'a HashMap<Slot, usize>,
2021    ) -> BankFieldsToSerialize<'a> {
2022        BankFieldsToSerialize {
2023            blockhash_queue: &self.blockhash_queue,
2024            ancestors,
2025            hash: *self.hash.read().unwrap(),
2026            parent_hash: self.parent_hash,
2027            parent_slot: self.parent_slot,
2028            hard_forks: &*self.hard_forks,
2029            transaction_count: self.transaction_count.load(Relaxed),
2030            tick_height: self.tick_height.load(Relaxed),
2031            signature_count: self.signature_count.load(Relaxed),
2032            capitalization: self.capitalization.load(Relaxed),
2033            max_tick_height: self.max_tick_height,
2034            hashes_per_tick: self.hashes_per_tick,
2035            ticks_per_slot: self.ticks_per_slot,
2036            ns_per_slot: self.ns_per_slot,
2037            genesis_creation_time: self.genesis_creation_time,
2038            slots_per_year: self.slots_per_year,
2039            slot: self.slot,
2040            epoch: self.epoch,
2041            block_height: self.block_height,
2042            collector_id: self.collector_id,
2043            collector_fees: self.collector_fees.load(Relaxed),
2044            fee_calculator: self.fee_calculator,
2045            fee_rate_governor: self.fee_rate_governor.clone(),
2046            collected_rent: self.collected_rent.load(Relaxed),
2047            rent_collector: self.rent_collector.clone(),
2048            epoch_schedule: self.epoch_schedule,
2049            inflation: *self.inflation.read().unwrap(),
2050            stakes: &self.stakes_cache,
2051            epoch_stakes: &self.epoch_stakes,
2052            is_delta: self.is_delta.load(Relaxed),
2053            accounts_data_len: self.load_accounts_data_size(),
2054        }
2055    }
2056
2057    pub fn collector_id(&self) -> &Pubkey {
2058        &self.collector_id
2059    }
2060
2061    pub fn genesis_creation_time(&self) -> UnixTimestamp {
2062        self.genesis_creation_time
2063    }
2064
2065    pub fn slot(&self) -> Slot {
2066        self.slot
2067    }
2068
2069    pub fn bank_id(&self) -> BankId {
2070        self.bank_id
2071    }
2072
2073    pub fn epoch(&self) -> Epoch {
2074        self.epoch
2075    }
2076
2077    pub fn first_normal_epoch(&self) -> Epoch {
2078        self.epoch_schedule().first_normal_epoch
2079    }
2080
2081    pub fn freeze_lock(&self) -> RwLockReadGuard<Hash> {
2082        self.hash.read().unwrap()
2083    }
2084
2085    pub fn hash(&self) -> Hash {
2086        *self.hash.read().unwrap()
2087    }
2088
2089    pub fn is_frozen(&self) -> bool {
2090        *self.hash.read().unwrap() != Hash::default()
2091    }
2092
2093    pub fn freeze_started(&self) -> bool {
2094        self.freeze_started.load(Relaxed)
2095    }
2096
2097    pub fn status_cache_ancestors(&self) -> Vec<u64> {
2098        let mut roots = self.status_cache.read().unwrap().roots().clone();
2099        let min = roots.iter().min().cloned().unwrap_or(0);
2100        for ancestor in self.ancestors.keys() {
2101            if ancestor >= min {
2102                roots.insert(ancestor);
2103            }
2104        }
2105
2106        let mut ancestors: Vec<_> = roots.into_iter().collect();
2107        #[allow(clippy::stable_sort_primitive)]
2108        ancestors.sort();
2109        ancestors
2110    }
2111
2112    /// computed unix_timestamp at this slot height
2113    pub fn unix_timestamp_from_genesis(&self) -> i64 {
2114        self.genesis_creation_time + ((self.slot as u128 * self.ns_per_slot) / 1_000_000_000) as i64
2115    }
2116
2117    fn update_sysvar_account<F>(&self, pubkey: &Pubkey, updater: F)
2118    where
2119        F: Fn(&Option<AccountSharedData>) -> AccountSharedData,
2120    {
2121        let old_account = self.get_account_with_fixed_root(pubkey);
2122        let mut new_account = updater(&old_account);
2123
2124        // When new sysvar comes into existence (with RENT_UNADJUSTED_INITIAL_BALANCE lamports),
2125        // this code ensures that the sysvar's balance is adjusted to be rent-exempt.
2126        //
2127        // More generally, this code always re-calculates for possible sysvar data size change,
2128        // although there is no such sysvars currently.
2129        self.adjust_sysvar_balance_for_rent(&mut new_account);
2130        self.store_account_and_update_capitalization(pubkey, &new_account);
2131    }
2132
2133    fn inherit_specially_retained_account_fields(
2134        &self,
2135        old_account: &Option<AccountSharedData>,
2136    ) -> InheritableAccountFields {
2137        const RENT_UNADJUSTED_INITIAL_BALANCE: u64 = 1;
2138
2139        (
2140            old_account
2141                .as_ref()
2142                .map(|a| a.lamports())
2143                .unwrap_or(RENT_UNADJUSTED_INITIAL_BALANCE),
2144            old_account
2145                .as_ref()
2146                .map(|a| a.rent_epoch())
2147                .unwrap_or(INITIAL_RENT_EPOCH),
2148        )
2149    }
2150
2151    pub fn clock(&self) -> sysvar::clock::Clock {
2152        from_account(&self.get_account(&sysvar::clock::id()).unwrap_or_default())
2153            .unwrap_or_default()
2154    }
2155
2156    fn update_clock(&self, parent_epoch: Option<Epoch>) {
2157        let mut unix_timestamp = self.clock().unix_timestamp;
2158        // set epoch_start_timestamp to None to warp timestamp
2159        let epoch_start_timestamp = {
2160            let epoch = if let Some(epoch) = parent_epoch {
2161                epoch
2162            } else {
2163                self.epoch()
2164            };
2165            let first_slot_in_epoch = self.epoch_schedule().get_first_slot_in_epoch(epoch);
2166            Some((first_slot_in_epoch, self.clock().epoch_start_timestamp))
2167        };
2168        let max_allowable_drift = MaxAllowableDrift {
2169            fast: MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST,
2170            slow: MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
2171        };
2172
2173        let ancestor_timestamp = self.clock().unix_timestamp;
2174        if let Some(timestamp_estimate) =
2175            self.get_timestamp_estimate(max_allowable_drift, epoch_start_timestamp)
2176        {
2177            unix_timestamp = timestamp_estimate;
2178            if timestamp_estimate < ancestor_timestamp {
2179                unix_timestamp = ancestor_timestamp;
2180            }
2181        }
2182        datapoint_info!(
2183            "bank-timestamp-correction",
2184            ("slot", self.slot(), i64),
2185            ("from_genesis", self.unix_timestamp_from_genesis(), i64),
2186            ("corrected", unix_timestamp, i64),
2187            ("ancestor_timestamp", ancestor_timestamp, i64),
2188        );
2189        let mut epoch_start_timestamp =
2190            // On epoch boundaries, update epoch_start_timestamp
2191            if parent_epoch.is_some() && parent_epoch.unwrap() != self.epoch() {
2192                unix_timestamp
2193            } else {
2194                self.clock().epoch_start_timestamp
2195            };
2196        if self.slot == 0 {
2197            unix_timestamp = self.unix_timestamp_from_genesis();
2198            epoch_start_timestamp = self.unix_timestamp_from_genesis();
2199        }
2200        let clock = sysvar::clock::Clock {
2201            slot: self.slot,
2202            epoch_start_timestamp,
2203            epoch: self.epoch_schedule().get_epoch(self.slot),
2204            leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
2205            unix_timestamp,
2206        };
2207        self.update_sysvar_account(&sysvar::clock::id(), |account| {
2208            create_account(
2209                &clock,
2210                self.inherit_specially_retained_account_fields(account),
2211            )
2212        });
2213    }
2214
2215    pub fn set_sysvar_for_tests<T>(&self, sysvar: &T)
2216    where
2217        T: Sysvar + SysvarId,
2218    {
2219        self.update_sysvar_account(&T::id(), |account| {
2220            create_account(
2221                sysvar,
2222                self.inherit_specially_retained_account_fields(account),
2223            )
2224        });
2225        // Simply force fill sysvar cache rather than checking which sysvar was
2226        // actually updated since tests don't need to be optimized for performance.
2227        self.reset_sysvar_cache();
2228        self.fill_missing_sysvar_cache_entries();
2229    }
2230
2231    fn update_slot_history(&self) {
2232        self.update_sysvar_account(&sysvar::slot_history::id(), |account| {
2233            let mut slot_history = account
2234                .as_ref()
2235                .map(|account| from_account::<SlotHistory, _>(account).unwrap())
2236                .unwrap_or_default();
2237            slot_history.add(self.slot());
2238            create_account(
2239                &slot_history,
2240                self.inherit_specially_retained_account_fields(account),
2241            )
2242        });
2243    }
2244
2245    fn update_slot_hashes(&self) {
2246        self.update_sysvar_account(&sysvar::slot_hashes::id(), |account| {
2247            let mut slot_hashes = account
2248                .as_ref()
2249                .map(|account| from_account::<SlotHashes, _>(account).unwrap())
2250                .unwrap_or_default();
2251            slot_hashes.add(self.parent_slot, self.parent_hash);
2252            create_account(
2253                &slot_hashes,
2254                self.inherit_specially_retained_account_fields(account),
2255            )
2256        });
2257    }
2258
2259    pub fn get_slot_history(&self) -> SlotHistory {
2260        from_account(&self.get_account(&sysvar::slot_history::id()).unwrap()).unwrap()
2261    }
2262
2263    fn update_epoch_stakes(&mut self, leader_schedule_epoch: Epoch) {
2264        // update epoch_stakes cache
2265        //  if my parent didn't populate for this staker's epoch, we've
2266        //  crossed a boundary
2267        if self.epoch_stakes.get(&leader_schedule_epoch).is_none() {
2268            self.epoch_stakes.retain(|&epoch, _| {
2269                epoch >= leader_schedule_epoch.saturating_sub(MAX_LEADER_SCHEDULE_STAKES)
2270            });
2271            let stakes = self.stakes_cache.stakes().clone();
2272            let stakes = Arc::new(StakesEnum::from(stakes));
2273            let new_epoch_stakes = EpochStakes::new(stakes, leader_schedule_epoch);
2274            {
2275                let vote_stakes: HashMap<_, _> = self
2276                    .stakes_cache
2277                    .stakes()
2278                    .vote_accounts()
2279                    .delegated_stakes()
2280                    .map(|(pubkey, stake)| (*pubkey, stake))
2281                    .collect();
2282                info!(
2283                    "new epoch stakes, epoch: {}, stakes: {:#?}, total_stake: {}",
2284                    leader_schedule_epoch,
2285                    vote_stakes,
2286                    new_epoch_stakes.total_stake(),
2287                );
2288            }
2289            self.epoch_stakes
2290                .insert(leader_schedule_epoch, new_epoch_stakes);
2291        }
2292    }
2293
2294    #[allow(deprecated)]
2295    fn update_fees(&self) {
2296        if !self
2297            .feature_set
2298            .is_active(&feature_set::disable_fees_sysvar::id())
2299        {
2300            self.update_sysvar_account(&sysvar::fees::id(), |account| {
2301                create_account(
2302                    &sysvar::fees::Fees::new(&self.fee_rate_governor.create_fee_calculator()),
2303                    self.inherit_specially_retained_account_fields(account),
2304                )
2305            });
2306        }
2307    }
2308
2309    fn update_rent(&self) {
2310        self.update_sysvar_account(&sysvar::rent::id(), |account| {
2311            create_account(
2312                &self.rent_collector.rent,
2313                self.inherit_specially_retained_account_fields(account),
2314            )
2315        });
2316    }
2317
2318    fn update_epoch_schedule(&self) {
2319        self.update_sysvar_account(&sysvar::epoch_schedule::id(), |account| {
2320            create_account(
2321                self.epoch_schedule(),
2322                self.inherit_specially_retained_account_fields(account),
2323            )
2324        });
2325    }
2326
2327    fn update_stake_history(&self, epoch: Option<Epoch>) {
2328        if epoch == Some(self.epoch()) {
2329            return;
2330        }
2331        // if I'm the first Bank in an epoch, ensure stake_history is updated
2332        self.update_sysvar_account(&sysvar::stake_history::id(), |account| {
2333            create_account::<sysvar::stake_history::StakeHistory>(
2334                self.stakes_cache.stakes().history(),
2335                self.inherit_specially_retained_account_fields(account),
2336            )
2337        });
2338    }
2339
2340    pub fn epoch_duration_in_years(&self, prev_epoch: Epoch) -> f64 {
2341        // period: time that has passed as a fraction of a year, basically the length of
2342        //  an epoch as a fraction of a year
2343        //  calculated as: slots_elapsed / (slots / year)
2344        self.epoch_schedule().get_slots_in_epoch(prev_epoch) as f64 / self.slots_per_year
2345    }
2346
2347    // Calculates the starting-slot for inflation from the activation slot.
2348    // This method assumes that `pico_inflation` will be enabled before `full_inflation`, giving
2349    // precedence to the latter. However, since `pico_inflation` is fixed-rate Inflation, should
2350    // `pico_inflation` be enabled 2nd, the incorrect start slot provided here should have no
2351    // effect on the inflation calculation.
2352    fn get_inflation_start_slot(&self) -> Slot {
2353        let mut slots = self
2354            .feature_set
2355            .full_inflation_features_enabled()
2356            .iter()
2357            .filter_map(|id| self.feature_set.activated_slot(id))
2358            .collect::<Vec<_>>();
2359        slots.sort_unstable();
2360        slots.first().cloned().unwrap_or_else(|| {
2361            self.feature_set
2362                .activated_slot(&feature_set::pico_inflation::id())
2363                .unwrap_or(0)
2364        })
2365    }
2366
2367    fn get_inflation_num_slots(&self) -> u64 {
2368        let inflation_activation_slot = self.get_inflation_start_slot();
2369        // Normalize inflation_start to align with the start of rewards accrual.
2370        let inflation_start_slot = self.epoch_schedule().get_first_slot_in_epoch(
2371            self.epoch_schedule()
2372                .get_epoch(inflation_activation_slot)
2373                .saturating_sub(1),
2374        );
2375        self.epoch_schedule().get_first_slot_in_epoch(self.epoch()) - inflation_start_slot
2376    }
2377
2378    pub fn slot_in_year_for_inflation(&self) -> f64 {
2379        let num_slots = self.get_inflation_num_slots();
2380
2381        // calculated as: num_slots / (slots / year)
2382        num_slots as f64 / self.slots_per_year
2383    }
2384
2385    fn calculate_previous_epoch_inflation_rewards(
2386        &self,
2387        prev_epoch_capitalization: u64,
2388        prev_epoch: Epoch,
2389    ) -> PrevEpochInflationRewards {
2390        let slot_in_year = self.slot_in_year_for_inflation();
2391        let (validator_rate, foundation_rate) = {
2392            let inflation = self.inflation.read().unwrap();
2393            (
2394                (*inflation).validator(slot_in_year),
2395                (*inflation).foundation(slot_in_year),
2396            )
2397        };
2398
2399        let prev_epoch_duration_in_years = self.epoch_duration_in_years(prev_epoch);
2400        let validator_rewards = (validator_rate
2401            * prev_epoch_capitalization as f64
2402            * prev_epoch_duration_in_years) as u64;
2403
2404        PrevEpochInflationRewards {
2405            validator_rewards,
2406            prev_epoch_duration_in_years,
2407            validator_rate,
2408            foundation_rate,
2409        }
2410    }
2411
2412    // update rewards based on the previous epoch
2413    fn update_rewards_with_thread_pool(
2414        &mut self,
2415        prev_epoch: Epoch,
2416        reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
2417        thread_pool: &ThreadPool,
2418        metrics: &mut RewardsMetrics,
2419    ) {
2420        let capitalization = self.capitalization();
2421        let PrevEpochInflationRewards {
2422            validator_rewards,
2423            prev_epoch_duration_in_years,
2424            validator_rate,
2425            foundation_rate,
2426        } = self.calculate_previous_epoch_inflation_rewards(capitalization, prev_epoch);
2427
2428        let old_vote_balance_and_staked = self.stakes_cache.stakes().vote_balance_and_staked();
2429        let update_rewards_from_cached_accounts = self
2430            .feature_set
2431            .is_active(&feature_set::update_rewards_from_cached_accounts::id());
2432
2433        self.pay_validator_rewards_with_thread_pool(
2434            prev_epoch,
2435            validator_rewards,
2436            reward_calc_tracer,
2437            self.credits_auto_rewind(),
2438            thread_pool,
2439            metrics,
2440            update_rewards_from_cached_accounts,
2441        );
2442
2443        let new_vote_balance_and_staked = self.stakes_cache.stakes().vote_balance_and_staked();
2444        let validator_rewards_paid = new_vote_balance_and_staked - old_vote_balance_and_staked;
2445        assert_eq!(
2446            validator_rewards_paid,
2447            u64::try_from(
2448                self.rewards
2449                    .read()
2450                    .unwrap()
2451                    .iter()
2452                    .map(|(_address, reward_info)| {
2453                        match reward_info.reward_type {
2454                            RewardType::Voting | RewardType::Staking => reward_info.lamports,
2455                            _ => 0,
2456                        }
2457                    })
2458                    .sum::<i64>()
2459            )
2460            .unwrap()
2461        );
2462
2463        // verify that we didn't pay any more than we expected to
2464        assert!(validator_rewards >= validator_rewards_paid);
2465
2466        info!(
2467            "distributed inflation: {} (rounded from: {})",
2468            validator_rewards_paid, validator_rewards
2469        );
2470        let (num_stake_accounts, num_vote_accounts) = {
2471            let stakes = self.stakes_cache.stakes();
2472            (
2473                stakes.stake_delegations().len(),
2474                stakes.vote_accounts().len(),
2475            )
2476        };
2477        self.capitalization
2478            .fetch_add(validator_rewards_paid, Relaxed);
2479
2480        let active_stake = if let Some(stake_history_entry) =
2481            self.stakes_cache.stakes().history().get(prev_epoch)
2482        {
2483            stake_history_entry.effective
2484        } else {
2485            0
2486        };
2487
2488        datapoint_warn!(
2489            "epoch_rewards",
2490            ("slot", self.slot, i64),
2491            ("epoch", prev_epoch, i64),
2492            ("validator_rate", validator_rate, f64),
2493            ("foundation_rate", foundation_rate, f64),
2494            ("epoch_duration_in_years", prev_epoch_duration_in_years, f64),
2495            ("validator_rewards", validator_rewards_paid, i64),
2496            ("active_stake", active_stake, i64),
2497            ("pre_capitalization", capitalization, i64),
2498            ("post_capitalization", self.capitalization(), i64),
2499            ("num_stake_accounts", num_stake_accounts as i64, i64),
2500            ("num_vote_accounts", num_vote_accounts as i64, i64),
2501        );
2502    }
2503
2504    /// map stake delegations into resolved (pubkey, account) pairs
2505    ///  returns a map (has to be copied) of loaded
2506    ///   ( Vec<(staker info)> (voter account) ) keyed by voter pubkey
2507    ///
2508    /// Filters out invalid pairs
2509    fn load_vote_and_stake_accounts_with_thread_pool(
2510        &self,
2511        thread_pool: &ThreadPool,
2512        reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
2513    ) -> LoadVoteAndStakeAccountsResult {
2514        let stakes = self.stakes_cache.stakes();
2515        let cached_vote_accounts = stakes.vote_accounts();
2516        let vote_with_stake_delegations_map = DashMap::with_capacity(cached_vote_accounts.len());
2517        let invalid_stake_keys: DashMap<Pubkey, InvalidCacheEntryReason> = DashMap::new();
2518        let invalid_vote_keys: DashMap<Pubkey, InvalidCacheEntryReason> = DashMap::new();
2519        let invalid_cached_stake_accounts = AtomicUsize::default();
2520        let invalid_cached_vote_accounts = AtomicUsize::default();
2521        let invalid_cached_stake_accounts_rent_epoch = AtomicUsize::default();
2522
2523        let stake_delegations = self.filter_stake_delegations(&stakes);
2524        thread_pool.install(|| {
2525            stake_delegations
2526                .into_par_iter()
2527                .for_each(|(stake_pubkey, cached_stake_account)| {
2528                    let delegation = cached_stake_account.delegation();
2529                    let vote_pubkey = &delegation.voter_pubkey;
2530                    if invalid_vote_keys.contains_key(vote_pubkey) {
2531                        return;
2532                    }
2533                    let stake_account = match self.get_account_with_fixed_root(stake_pubkey) {
2534                        Some(stake_account) => stake_account,
2535                        None => {
2536                            invalid_stake_keys
2537                                .insert(*stake_pubkey, InvalidCacheEntryReason::Missing);
2538                            invalid_cached_stake_accounts.fetch_add(1, Relaxed);
2539                            return;
2540                        }
2541                    };
2542                    if cached_stake_account.account() != &stake_account {
2543                        invalid_cached_stake_accounts.fetch_add(1, Relaxed);
2544                        let cached_stake_account = cached_stake_account.account();
2545                        if cached_stake_account.lamports() == stake_account.lamports()
2546                            && cached_stake_account.data() == stake_account.data()
2547                            && cached_stake_account.owner() == stake_account.owner()
2548                            && cached_stake_account.executable() == stake_account.executable()
2549                        {
2550                            invalid_cached_stake_accounts_rent_epoch.fetch_add(1, Relaxed);
2551                        } else {
2552                            debug!(
2553                                "cached stake account mismatch: {}: {:?}, {:?}",
2554                                stake_pubkey, stake_account, cached_stake_account
2555                            );
2556                        }
2557                    }
2558                    let stake_account = match StakeAccount::<()>::try_from(stake_account) {
2559                        Ok(stake_account) => stake_account,
2560                        Err(stake_account::Error::InvalidOwner { .. }) => {
2561                            invalid_stake_keys
2562                                .insert(*stake_pubkey, InvalidCacheEntryReason::WrongOwner);
2563                            return;
2564                        }
2565                        Err(stake_account::Error::InstructionError(_)) => {
2566                            invalid_stake_keys
2567                                .insert(*stake_pubkey, InvalidCacheEntryReason::BadState);
2568                            return;
2569                        }
2570                        Err(stake_account::Error::InvalidDelegation(_)) => {
2571                            // This should not happen.
2572                            error!(
2573                                "Unexpected code path! StakeAccount<()> \
2574                                should not check if stake-state is a \
2575                                Delegation."
2576                            );
2577                            return;
2578                        }
2579                    };
2580                    let stake_delegation = (*stake_pubkey, stake_account);
2581                    let mut vote_delegations = if let Some(vote_delegations) =
2582                        vote_with_stake_delegations_map.get_mut(vote_pubkey)
2583                    {
2584                        vote_delegations
2585                    } else {
2586                        let cached_vote_account = cached_vote_accounts.get(vote_pubkey);
2587                        let vote_account = match self.get_account_with_fixed_root(vote_pubkey) {
2588                            Some(vote_account) => {
2589                                if vote_account.owner() != &solana_vote_program::id() {
2590                                    invalid_vote_keys
2591                                        .insert(*vote_pubkey, InvalidCacheEntryReason::WrongOwner);
2592                                    if cached_vote_account.is_some() {
2593                                        invalid_cached_vote_accounts.fetch_add(1, Relaxed);
2594                                    }
2595                                    return;
2596                                }
2597                                vote_account
2598                            }
2599                            None => {
2600                                if cached_vote_account.is_some() {
2601                                    invalid_cached_vote_accounts.fetch_add(1, Relaxed);
2602                                }
2603                                invalid_vote_keys
2604                                    .insert(*vote_pubkey, InvalidCacheEntryReason::Missing);
2605                                return;
2606                            }
2607                        };
2608
2609                        let vote_state = if let Ok(vote_state) =
2610                            StateMut::<VoteStateVersions>::state(&vote_account)
2611                        {
2612                            vote_state.convert_to_current()
2613                        } else {
2614                            invalid_vote_keys
2615                                .insert(*vote_pubkey, InvalidCacheEntryReason::BadState);
2616                            if cached_vote_account.is_some() {
2617                                invalid_cached_vote_accounts.fetch_add(1, Relaxed);
2618                            }
2619                            return;
2620                        };
2621                        match cached_vote_account {
2622                            Some(cached_vote_account)
2623                                if cached_vote_account.account() == &vote_account => {}
2624                            _ => {
2625                                invalid_cached_vote_accounts.fetch_add(1, Relaxed);
2626                            }
2627                        };
2628                        vote_with_stake_delegations_map
2629                            .entry(*vote_pubkey)
2630                            .or_insert_with(|| VoteWithStakeDelegations {
2631                                vote_state: Arc::new(vote_state),
2632                                vote_account,
2633                                delegations: vec![],
2634                            })
2635                    };
2636
2637                    if let Some(reward_calc_tracer) = reward_calc_tracer.as_ref() {
2638                        reward_calc_tracer(&RewardCalculationEvent::Staking(
2639                            stake_pubkey,
2640                            &InflationPointCalculationEvent::Delegation(
2641                                delegation,
2642                                solana_vote_program::id(),
2643                            ),
2644                        ));
2645                    }
2646
2647                    vote_delegations.delegations.push(stake_delegation);
2648                });
2649        });
2650        invalid_cached_stake_accounts.fetch_add(invalid_stake_keys.len(), Relaxed);
2651        LoadVoteAndStakeAccountsResult {
2652            vote_with_stake_delegations_map,
2653            invalid_vote_keys,
2654            invalid_stake_keys,
2655            invalid_cached_vote_accounts: invalid_cached_vote_accounts.into_inner(),
2656            invalid_cached_stake_accounts: invalid_cached_stake_accounts.into_inner(),
2657            invalid_cached_stake_accounts_rent_epoch: invalid_cached_stake_accounts_rent_epoch
2658                .into_inner(),
2659            vote_accounts_cache_miss_count: 0,
2660        }
2661    }
2662
2663    fn filter_stake_delegations<'a>(
2664        &self,
2665        stakes: &'a Stakes<StakeAccount<Delegation>>,
2666    ) -> Vec<(&'a Pubkey, &'a StakeAccount<Delegation>)> {
2667        if self
2668            .feature_set
2669            .is_active(&feature_set::stake_minimum_delegation_for_rewards::id())
2670        {
2671            let num_stake_delegations = stakes.stake_delegations().len();
2672            let min_stake_delegation =
2673                solana_stake_program::get_minimum_delegation(&self.feature_set)
2674                    .max(LAMPORTS_PER_SAFE);
2675
2676            let (stake_delegations, filter_timer) = measure!(stakes
2677                .stake_delegations()
2678                .iter()
2679                .filter(|(_stake_pubkey, cached_stake_account)| {
2680                    cached_stake_account.delegation().stake >= min_stake_delegation
2681                })
2682                .collect::<Vec<_>>());
2683
2684            datapoint_info!(
2685                "stake_account_filter_time",
2686                ("filter_time_us", filter_timer.as_us(), i64),
2687                ("num_stake_delegations_before", num_stake_delegations, i64),
2688                ("num_stake_delegations_after", stake_delegations.len(), i64)
2689            );
2690            stake_delegations
2691        } else {
2692            stakes.stake_delegations().iter().collect()
2693        }
2694    }
2695
2696    fn load_vote_and_stake_accounts<F>(
2697        &self,
2698        thread_pool: &ThreadPool,
2699        reward_calc_tracer: Option<F>,
2700    ) -> LoadVoteAndStakeAccountsResult
2701    where
2702        F: Fn(&RewardCalculationEvent) + Send + Sync,
2703    {
2704        let stakes = self.stakes_cache.stakes();
2705        let stake_delegations = self.filter_stake_delegations(&stakes);
2706
2707        // Obtain all unique voter pubkeys from stake delegations.
2708        fn merge(mut acc: HashSet<Pubkey>, other: HashSet<Pubkey>) -> HashSet<Pubkey> {
2709            if acc.len() < other.len() {
2710                return merge(other, acc);
2711            }
2712            acc.extend(other);
2713            acc
2714        }
2715        let voter_pubkeys = thread_pool.install(|| {
2716            stake_delegations
2717                .par_iter()
2718                .fold(
2719                    HashSet::default,
2720                    |mut voter_pubkeys, (_stake_pubkey, stake_account)| {
2721                        let delegation = stake_account.delegation();
2722                        voter_pubkeys.insert(delegation.voter_pubkey);
2723                        voter_pubkeys
2724                    },
2725                )
2726                .reduce(HashSet::default, merge)
2727        });
2728        // Obtain vote-accounts for unique voter pubkeys.
2729        let cached_vote_accounts = stakes.vote_accounts();
2730        let solana_vote_program: Pubkey = solana_vote_program::id();
2731        let vote_accounts_cache_miss_count = AtomicUsize::default();
2732        let get_vote_account = |vote_pubkey: &Pubkey| -> Option<VoteAccount> {
2733            if let Some(vote_account) = cached_vote_accounts.get(vote_pubkey) {
2734                return Some(vote_account.clone());
2735            }
2736            // If accounts-db contains a valid vote account, then it should
2737            // already have been cached in cached_vote_accounts; so the code
2738            // below is only for sanity check, and can be removed once
2739            // vote_accounts_cache_miss_count is shown to be always zero.
2740            let account = self.get_account_with_fixed_root(vote_pubkey)?;
2741            if account.owner() == &solana_vote_program
2742                && VoteState::deserialize(account.data()).is_ok()
2743            {
2744                vote_accounts_cache_miss_count.fetch_add(1, Relaxed);
2745            }
2746            VoteAccount::try_from(account).ok()
2747        };
2748        let invalid_vote_keys = DashMap::<Pubkey, InvalidCacheEntryReason>::new();
2749        let make_vote_delegations_entry = |vote_pubkey| {
2750            let vote_account = match get_vote_account(&vote_pubkey) {
2751                Some(vote_account) => vote_account,
2752                None => {
2753                    invalid_vote_keys.insert(vote_pubkey, InvalidCacheEntryReason::Missing);
2754                    return None;
2755                }
2756            };
2757            if vote_account.owner() != &solana_vote_program {
2758                invalid_vote_keys.insert(vote_pubkey, InvalidCacheEntryReason::WrongOwner);
2759                return None;
2760            }
2761            let vote_state = match vote_account.vote_state().deref() {
2762                Ok(vote_state) => vote_state.clone(),
2763                Err(_) => {
2764                    invalid_vote_keys.insert(vote_pubkey, InvalidCacheEntryReason::BadState);
2765                    return None;
2766                }
2767            };
2768            let vote_with_stake_delegations = VoteWithStakeDelegations {
2769                vote_state: Arc::new(vote_state),
2770                vote_account: AccountSharedData::from(vote_account),
2771                delegations: Vec::default(),
2772            };
2773            Some((vote_pubkey, vote_with_stake_delegations))
2774        };
2775        let vote_with_stake_delegations_map: DashMap<Pubkey, VoteWithStakeDelegations> =
2776            thread_pool.install(|| {
2777                voter_pubkeys
2778                    .into_par_iter()
2779                    .filter_map(make_vote_delegations_entry)
2780                    .collect()
2781            });
2782        // Join stake accounts with vote-accounts.
2783        let push_stake_delegation = |(stake_pubkey, stake_account): (&Pubkey, &StakeAccount<_>)| {
2784            let delegation = stake_account.delegation();
2785            let mut vote_delegations =
2786                match vote_with_stake_delegations_map.get_mut(&delegation.voter_pubkey) {
2787                    Some(vote_delegations) => vote_delegations,
2788                    None => return,
2789                };
2790            if let Some(reward_calc_tracer) = reward_calc_tracer.as_ref() {
2791                let delegation =
2792                    InflationPointCalculationEvent::Delegation(delegation, solana_vote_program);
2793                let event = RewardCalculationEvent::Staking(stake_pubkey, &delegation);
2794                reward_calc_tracer(&event);
2795            }
2796            let stake_account = StakeAccount::from(stake_account.clone());
2797            let stake_delegation = (*stake_pubkey, stake_account);
2798            vote_delegations.delegations.push(stake_delegation);
2799        };
2800        thread_pool.install(|| {
2801            stake_delegations
2802                .into_par_iter()
2803                .for_each(push_stake_delegation);
2804        });
2805        LoadVoteAndStakeAccountsResult {
2806            vote_with_stake_delegations_map,
2807            invalid_vote_keys,
2808            invalid_stake_keys: DashMap::default(),
2809            invalid_cached_vote_accounts: 0,
2810            invalid_cached_stake_accounts: 0,
2811            invalid_cached_stake_accounts_rent_epoch: 0,
2812            vote_accounts_cache_miss_count: vote_accounts_cache_miss_count.into_inner(),
2813        }
2814    }
2815
2816    /// iterate over all stakes, redeem vote credits for each stake we can
2817    /// successfully load and parse, return the lamport value of one point
2818    fn pay_validator_rewards_with_thread_pool(
2819        &mut self,
2820        rewarded_epoch: Epoch,
2821        rewards: u64,
2822        reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
2823        credits_auto_rewind: bool,
2824        thread_pool: &ThreadPool,
2825        metrics: &mut RewardsMetrics,
2826        update_rewards_from_cached_accounts: bool,
2827    ) -> f64 {
2828        let stake_history = self.stakes_cache.stakes().history().clone();
2829        let vote_with_stake_delegations_map = {
2830            let mut m = Measure::start("load_vote_and_stake_accounts_us");
2831            let LoadVoteAndStakeAccountsResult {
2832                vote_with_stake_delegations_map,
2833                invalid_stake_keys,
2834                invalid_vote_keys,
2835                invalid_cached_vote_accounts,
2836                invalid_cached_stake_accounts,
2837                invalid_cached_stake_accounts_rent_epoch,
2838                vote_accounts_cache_miss_count,
2839            } = if update_rewards_from_cached_accounts {
2840                self.load_vote_and_stake_accounts(thread_pool, reward_calc_tracer.as_ref())
2841            } else {
2842                self.load_vote_and_stake_accounts_with_thread_pool(
2843                    thread_pool,
2844                    reward_calc_tracer.as_ref(),
2845                )
2846            };
2847            m.stop();
2848            metrics
2849                .load_vote_and_stake_accounts_us
2850                .fetch_add(m.as_us(), Relaxed);
2851            metrics.invalid_cached_vote_accounts += invalid_cached_vote_accounts;
2852            metrics.invalid_cached_stake_accounts += invalid_cached_stake_accounts;
2853            metrics.invalid_cached_stake_accounts_rent_epoch +=
2854                invalid_cached_stake_accounts_rent_epoch;
2855            metrics.vote_accounts_cache_miss_count += vote_accounts_cache_miss_count;
2856            self.stakes_cache.handle_invalid_keys(
2857                invalid_stake_keys,
2858                invalid_vote_keys,
2859                self.slot(),
2860            );
2861            vote_with_stake_delegations_map
2862        };
2863
2864        let mut m = Measure::start("calculate_points");
2865        let points: u128 = thread_pool.install(|| {
2866            vote_with_stake_delegations_map
2867                .par_iter()
2868                .map(|entry| {
2869                    let VoteWithStakeDelegations {
2870                        vote_state,
2871                        delegations,
2872                        ..
2873                    } = entry.value();
2874
2875                    delegations
2876                        .par_iter()
2877                        .map(|(_stake_pubkey, stake_account)| {
2878                            stake_state::calculate_points(
2879                                stake_account.stake_state(),
2880                                vote_state,
2881                                Some(&stake_history),
2882                            )
2883                            .unwrap_or(0)
2884                        })
2885                        .sum::<u128>()
2886                })
2887                .sum()
2888        });
2889        m.stop();
2890        metrics.calculate_points_us.fetch_add(m.as_us(), Relaxed);
2891
2892        if points == 0 {
2893            return 0.0;
2894        }
2895
2896        // pay according to point value
2897        let point_value = PointValue { rewards, points };
2898        let vote_account_rewards: DashMap<Pubkey, (AccountSharedData, u8, u64, bool)> =
2899            DashMap::with_capacity(vote_with_stake_delegations_map.len());
2900        let stake_delegation_iterator = vote_with_stake_delegations_map.into_par_iter().flat_map(
2901            |(
2902                vote_pubkey,
2903                VoteWithStakeDelegations {
2904                    vote_state,
2905                    vote_account,
2906                    delegations,
2907                },
2908            )| {
2909                vote_account_rewards
2910                    .insert(vote_pubkey, (vote_account, vote_state.commission, 0, false));
2911                delegations
2912                    .into_par_iter()
2913                    .map(move |delegation| (vote_pubkey, Arc::clone(&vote_state), delegation))
2914            },
2915        );
2916
2917        let mut m = Measure::start("redeem_rewards");
2918        let stake_rewards: Vec<StakeReward> = thread_pool.install(|| {
2919            stake_delegation_iterator
2920                .filter_map(|(vote_pubkey, vote_state, (stake_pubkey, stake_account))| {
2921                    // curry closure to add the contextual stake_pubkey
2922                    let reward_calc_tracer = reward_calc_tracer.as_ref().map(|outer| {
2923                        // inner
2924                        move |inner_event: &_| {
2925                            outer(&RewardCalculationEvent::Staking(&stake_pubkey, inner_event))
2926                        }
2927                    });
2928                    let (mut stake_account, stake_state) =
2929                        <(AccountSharedData, StakeState)>::from(stake_account);
2930                    let redeemed = stake_state::redeem_rewards(
2931                        rewarded_epoch,
2932                        stake_state,
2933                        &mut stake_account,
2934                        &vote_state,
2935                        &point_value,
2936                        Some(&stake_history),
2937                        reward_calc_tracer.as_ref(),
2938                        credits_auto_rewind,
2939                    );
2940                    if let Ok((stakers_reward, voters_reward)) = redeemed {
2941                        // track voter rewards
2942                        if let Some((
2943                            _vote_account,
2944                            _commission,
2945                            vote_rewards_sum,
2946                            vote_needs_store,
2947                        )) = vote_account_rewards.get_mut(&vote_pubkey).as_deref_mut()
2948                        {
2949                            *vote_needs_store = true;
2950                            *vote_rewards_sum = vote_rewards_sum.saturating_add(voters_reward);
2951                        }
2952
2953                        let post_balance = stake_account.lamports();
2954                        return Some(StakeReward {
2955                            stake_pubkey,
2956                            stake_reward_info: RewardInfo {
2957                                reward_type: RewardType::Staking,
2958                                lamports: i64::try_from(stakers_reward).unwrap(),
2959                                post_balance,
2960                                commission: Some(vote_state.commission),
2961                            },
2962                            stake_account,
2963                        });
2964                    } else {
2965                        debug!(
2966                            "stake_state::redeem_rewards() failed for {}: {:?}",
2967                            stake_pubkey, redeemed
2968                        );
2969                    }
2970                    None
2971                })
2972                .collect()
2973        });
2974        m.stop();
2975        metrics.redeem_rewards_us += m.as_us();
2976
2977        // store stake account even if stakers_reward is 0
2978        // because credits observed has changed
2979        let mut m = Measure::start("store_stake_account");
2980        self.store_accounts((self.slot(), &stake_rewards[..]));
2981        m.stop();
2982        metrics
2983            .store_stake_accounts_us
2984            .fetch_add(m.as_us(), Relaxed);
2985
2986        let mut m = Measure::start("store_vote_accounts");
2987        let mut vote_rewards = vote_account_rewards
2988            .into_iter()
2989            .filter_map(
2990                |(vote_pubkey, (mut vote_account, commission, vote_rewards, vote_needs_store))| {
2991                    if let Err(err) = vote_account.checked_add_lamports(vote_rewards) {
2992                        debug!("reward redemption failed for {}: {:?}", vote_pubkey, err);
2993                        return None;
2994                    }
2995
2996                    if vote_needs_store {
2997                        self.store_account(&vote_pubkey, &vote_account);
2998                    }
2999
3000                    Some((
3001                        vote_pubkey,
3002                        RewardInfo {
3003                            reward_type: RewardType::Voting,
3004                            lamports: vote_rewards as i64,
3005                            post_balance: vote_account.lamports(),
3006                            commission: Some(commission),
3007                        },
3008                    ))
3009                },
3010            )
3011            .collect::<Vec<_>>();
3012
3013        m.stop();
3014        metrics.store_vote_accounts_us.fetch_add(m.as_us(), Relaxed);
3015
3016        let additional_reserve = stake_rewards.len() + vote_rewards.len();
3017        {
3018            let mut rewards = self.rewards.write().unwrap();
3019            rewards.reserve(additional_reserve);
3020            rewards.append(&mut vote_rewards);
3021            stake_rewards
3022                .into_iter()
3023                .filter(|x| x.get_stake_reward() > 0)
3024                .for_each(|x| rewards.push((x.stake_pubkey, x.stake_reward_info)));
3025        }
3026
3027        point_value.rewards as f64 / point_value.points as f64
3028    }
3029
3030    fn update_recent_blockhashes_locked(&self, locked_blockhash_queue: &BlockhashQueue) {
3031        #[allow(deprecated)]
3032        self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
3033            let recent_blockhash_iter = locked_blockhash_queue.get_recent_blockhashes();
3034            recent_blockhashes_account::create_account_with_data_and_fields(
3035                recent_blockhash_iter,
3036                self.inherit_specially_retained_account_fields(account),
3037            )
3038        });
3039    }
3040
3041    pub fn update_recent_blockhashes(&self) {
3042        let blockhash_queue = self.blockhash_queue.read().unwrap();
3043        self.update_recent_blockhashes_locked(&blockhash_queue);
3044    }
3045
3046    fn get_timestamp_estimate(
3047        &self,
3048        max_allowable_drift: MaxAllowableDrift,
3049        epoch_start_timestamp: Option<(Slot, UnixTimestamp)>,
3050    ) -> Option<UnixTimestamp> {
3051        let mut get_timestamp_estimate_time = Measure::start("get_timestamp_estimate");
3052        let slots_per_epoch = self.epoch_schedule().slots_per_epoch;
3053        let vote_accounts = self.vote_accounts();
3054        let recent_timestamps = vote_accounts.iter().filter_map(|(pubkey, (_, account))| {
3055            let vote_state = account.vote_state();
3056            let vote_state = vote_state.as_ref().ok()?;
3057            let slot_delta = self.slot().checked_sub(vote_state.last_timestamp.slot)?;
3058            (slot_delta <= slots_per_epoch).then(|| {
3059                (
3060                    *pubkey,
3061                    (
3062                        vote_state.last_timestamp.slot,
3063                        vote_state.last_timestamp.timestamp,
3064                    ),
3065                )
3066            })
3067        });
3068        let slot_duration = Duration::from_nanos(self.ns_per_slot as u64);
3069        let epoch = self.epoch_schedule().get_epoch(self.slot());
3070        let stakes = self.epoch_vote_accounts(epoch)?;
3071        let stake_weighted_timestamp = calculate_stake_weighted_timestamp(
3072            recent_timestamps,
3073            stakes,
3074            self.slot(),
3075            slot_duration,
3076            epoch_start_timestamp,
3077            max_allowable_drift,
3078            self.feature_set
3079                .is_active(&feature_set::warp_timestamp_again::id()),
3080        );
3081        get_timestamp_estimate_time.stop();
3082        datapoint_info!(
3083            "bank-timestamp",
3084            (
3085                "get_timestamp_estimate_us",
3086                get_timestamp_estimate_time.as_us(),
3087                i64
3088            ),
3089        );
3090        stake_weighted_timestamp
3091    }
3092
3093    // Distribute collected transaction fees for this slot to collector_id (= current leader).
3094    //
3095    // Each validator is incentivized to process more transactions to earn more transaction fees.
3096    // Transaction fees are rewarded for the computing resource utilization cost, directly
3097    // proportional to their actual processing power.
3098    //
3099    // collector_id is rotated according to stake-weighted leader schedule. So the opportunity of
3100    // earning transaction fees are fairly distributed by stake. And missing the opportunity
3101    // (not producing a block as a leader) earns nothing. So, being online is incentivized as a
3102    // form of transaction fees as well.
3103    //
3104    // On the other hand, rent fees are distributed under slightly different philosophy, while
3105    // still being stake-weighted.
3106    // Ref: distribute_rent_to_validators
3107    fn collect_fees(&self) {
3108        let collector_fees = self.collector_fees.load(Relaxed) as u64;
3109
3110        if collector_fees != 0 {
3111            let (deposit, mut burn) = self.fee_rate_governor.burn(collector_fees);
3112            // burn a portion of fees
3113            debug!(
3114                "distributed fee: {} (rounded from: {}, burned: {})",
3115                deposit, collector_fees, burn
3116            );
3117
3118            match self.deposit(&self.collector_id, deposit) {
3119                Ok(post_balance) => {
3120                    if deposit != 0 {
3121                        self.rewards.write().unwrap().push((
3122                            self.collector_id,
3123                            RewardInfo {
3124                                reward_type: RewardType::Fee,
3125                                lamports: deposit as i64,
3126                                post_balance,
3127                                commission: None,
3128                            },
3129                        ));
3130                    }
3131                }
3132                Err(_) => {
3133                    error!(
3134                        "Burning {} fee instead of crediting {}",
3135                        deposit, self.collector_id
3136                    );
3137                    inc_new_counter_error!("bank-burned_fee_lamports", deposit as usize);
3138                    burn += deposit;
3139                }
3140            }
3141            self.capitalization.fetch_sub(burn, Relaxed);
3142        }
3143    }
3144
3145    pub fn rehash(&self) {
3146        let mut hash = self.hash.write().unwrap();
3147        let new = self.hash_internal_state();
3148        if new != *hash {
3149            warn!("Updating bank hash to {}", new);
3150            *hash = new;
3151        }
3152    }
3153
3154    pub fn freeze(&self) {
3155        // This lock prevents any new commits from BankingStage
3156        // `process_and_record_transactions_locked()` from coming
3157        // in after the last tick is observed. This is because in
3158        // BankingStage, any transaction successfully recorded in
3159        // `record_transactions()` is recorded after this `hash` lock
3160        // is grabbed. At the time of the successful record,
3161        // this means the PoH has not yet reached the last tick,
3162        // so this means freeze() hasn't been called yet. And because
3163        // BankingStage doesn't release this hash lock until both
3164        // record and commit are finished, those transactions will be
3165        // committed before this write lock can be obtained here.
3166        let mut hash = self.hash.write().unwrap();
3167        if *hash == Hash::default() {
3168            // finish up any deferred changes to account state
3169            self.collect_rent_eagerly(false);
3170            self.collect_fees();
3171            self.distribute_rent();
3172            self.update_slot_history();
3173            self.run_incinerator();
3174
3175            // freeze is a one-way trip, idempotent
3176            self.freeze_started.store(true, Relaxed);
3177            *hash = self.hash_internal_state();
3178            self.rc.accounts.accounts_db.mark_slot_frozen(self.slot());
3179        }
3180    }
3181
3182    // dangerous; don't use this; this is only needed for ledger-tool's special command
3183    pub fn unfreeze_for_ledger_tool(&self) {
3184        self.freeze_started.store(false, Relaxed);
3185    }
3186
3187    pub fn epoch_schedule(&self) -> &EpochSchedule {
3188        &self.epoch_schedule
3189    }
3190
3191    /// squash the parent's state up into this Bank,
3192    ///   this Bank becomes a root
3193    pub fn squash(&self) -> SquashTiming {
3194        self.freeze();
3195
3196        //this bank and all its parents are now on the rooted path
3197        let mut roots = vec![self.slot()];
3198        roots.append(&mut self.parents().iter().map(|p| p.slot()).collect());
3199
3200        let mut total_index_us = 0;
3201        let mut total_cache_us = 0;
3202        let mut total_store_us = 0;
3203
3204        let mut squash_accounts_time = Measure::start("squash_accounts_time");
3205        for slot in roots.iter().rev() {
3206            // root forks cannot be purged
3207            let add_root_timing = self.rc.accounts.add_root(*slot);
3208            total_index_us += add_root_timing.index_us;
3209            total_cache_us += add_root_timing.cache_us;
3210            total_store_us += add_root_timing.store_us;
3211        }
3212        squash_accounts_time.stop();
3213
3214        *self.rc.parent.write().unwrap() = None;
3215
3216        let mut squash_cache_time = Measure::start("squash_cache_time");
3217        roots
3218            .iter()
3219            .for_each(|slot| self.status_cache.write().unwrap().add_root(*slot));
3220        squash_cache_time.stop();
3221
3222        SquashTiming {
3223            squash_accounts_ms: squash_accounts_time.as_ms(),
3224            squash_accounts_index_ms: total_index_us / 1000,
3225            squash_accounts_cache_ms: total_cache_us / 1000,
3226            squash_accounts_store_ms: total_store_us / 1000,
3227
3228            squash_cache_ms: squash_cache_time.as_ms(),
3229        }
3230    }
3231
3232    /// Return the more recent checkpoint of this bank instance.
3233    pub fn parent(&self) -> Option<Arc<Bank>> {
3234        self.rc.parent.read().unwrap().clone()
3235    }
3236
3237    pub fn parent_slot(&self) -> Slot {
3238        self.parent_slot
3239    }
3240
3241    pub fn parent_hash(&self) -> Hash {
3242        self.parent_hash
3243    }
3244
3245    fn process_genesis_config(&mut self, genesis_config: &GenesisConfig) {
3246        // Bootstrap validator collects fees until `new_from_parent` is called.
3247        self.fee_rate_governor = genesis_config.fee_rate_governor.clone();
3248        self.fee_calculator = self.fee_rate_governor.create_fee_calculator();
3249
3250        for (pubkey, account) in genesis_config.accounts.iter() {
3251            assert!(
3252                self.get_account(pubkey).is_none(),
3253                "{} repeated in genesis config",
3254                pubkey
3255            );
3256            self.store_account(pubkey, account);
3257            self.capitalization.fetch_add(account.lamports(), Relaxed);
3258            self.accounts_data_size_initial += account.data().len() as u64;
3259        }
3260        // updating sysvars (the fees sysvar in this case) now depends on feature activations in
3261        // genesis_config.accounts above
3262        self.update_fees();
3263
3264        for (pubkey, account) in genesis_config.rewards_pools.iter() {
3265            assert!(
3266                self.get_account(pubkey).is_none(),
3267                "{} repeated in genesis config",
3268                pubkey
3269            );
3270            self.store_account(pubkey, account);
3271            self.accounts_data_size_initial += account.data().len() as u64;
3272        }
3273
3274        // highest staked node is the first collector
3275        self.collector_id = self
3276            .stakes_cache
3277            .stakes()
3278            .highest_staked_node()
3279            .unwrap_or_default();
3280
3281        self.blockhash_queue.write().unwrap().genesis_hash(
3282            &genesis_config.hash(),
3283            self.fee_rate_governor.lamports_per_signature,
3284        );
3285
3286        self.hashes_per_tick = genesis_config.hashes_per_tick();
3287        self.ticks_per_slot = genesis_config.ticks_per_slot();
3288        self.ns_per_slot = genesis_config.ns_per_slot();
3289        self.genesis_creation_time = genesis_config.creation_time;
3290        self.max_tick_height = (self.slot + 1) * self.ticks_per_slot;
3291        self.slots_per_year = genesis_config.slots_per_year();
3292
3293        self.epoch_schedule = genesis_config.epoch_schedule;
3294
3295        self.inflation = Arc::new(RwLock::new(genesis_config.inflation));
3296
3297        self.rent_collector = RentCollector::new(
3298            self.epoch,
3299            *self.epoch_schedule(),
3300            self.slots_per_year,
3301            genesis_config.rent,
3302        );
3303
3304        // Add additional builtin programs specified in the genesis config
3305        for (name, program_id) in &genesis_config.native_instruction_processors {
3306            self.add_builtin_account(name, program_id, false);
3307        }
3308    }
3309
3310    fn burn_and_purge_account(&self, program_id: &Pubkey, mut account: AccountSharedData) {
3311        let old_data_size = account.data().len();
3312        self.capitalization.fetch_sub(account.lamports(), Relaxed);
3313        // Both resetting account balance to 0 and zeroing the account data
3314        // is needed to really purge from AccountsDb and flush the Stakes cache
3315        account.set_lamports(0);
3316        account.data_as_mut_slice().fill(0);
3317        self.store_account(program_id, &account);
3318        self.calculate_and_update_accounts_data_size_delta_off_chain(old_data_size, 0);
3319    }
3320
3321    // NOTE: must hold idempotent for the same set of arguments
3322    /// Add a builtin program account
3323    pub fn add_builtin_account(&self, name: &str, program_id: &Pubkey, must_replace: bool) {
3324        let existing_genuine_program =
3325            self.get_account_with_fixed_root(program_id)
3326                .and_then(|account| {
3327                    // it's very unlikely to be squatted at program_id as non-system account because of burden to
3328                    // find victim's pubkey/hash. So, when account.owner is indeed native_loader's, it's
3329                    // safe to assume it's a genuine program.
3330                    if native_loader::check_id(account.owner()) {
3331                        Some(account)
3332                    } else {
3333                        // malicious account is pre-occupying at program_id
3334                        self.burn_and_purge_account(program_id, account);
3335                        None
3336                    }
3337                });
3338
3339        if must_replace {
3340            // updating builtin program
3341            match &existing_genuine_program {
3342                None => panic!(
3343                    "There is no account to replace with builtin program ({}, {}).",
3344                    name, program_id
3345                ),
3346                Some(account) => {
3347                    if *name == String::from_utf8_lossy(account.data()) {
3348                        // The existing account is well formed
3349                        return;
3350                    }
3351                }
3352            }
3353        } else {
3354            // introducing builtin program
3355            if existing_genuine_program.is_some() {
3356                // The existing account is sufficient
3357                return;
3358            }
3359        }
3360
3361        assert!(
3362            !self.freeze_started(),
3363            "Can't change frozen bank by adding not-existing new builtin program ({}, {}). \
3364            Maybe, inconsistent program activation is detected on snapshot restore?",
3365            name,
3366            program_id
3367        );
3368
3369        // Add a bogus executable builtin account, which will be loaded and ignored.
3370        let account = native_loader::create_loadable_account_with_fields(
3371            name,
3372            self.inherit_specially_retained_account_fields(&existing_genuine_program),
3373        );
3374        self.store_account_and_update_capitalization(program_id, &account);
3375    }
3376
3377    /// Add a precompiled program account
3378    pub fn add_precompiled_account(&self, program_id: &Pubkey) {
3379        self.add_precompiled_account_with_owner(program_id, native_loader::id())
3380    }
3381
3382    // Used by tests to simulate clusters with precompiles that aren't owned by the native loader
3383    fn add_precompiled_account_with_owner(&self, program_id: &Pubkey, owner: Pubkey) {
3384        if let Some(account) = self.get_account_with_fixed_root(program_id) {
3385            if account.executable() {
3386                // The account is already executable, that's all we need
3387                return;
3388            } else {
3389                // malicious account is pre-occupying at program_id
3390                self.burn_and_purge_account(program_id, account);
3391            }
3392        };
3393
3394        assert!(
3395            !self.freeze_started(),
3396            "Can't change frozen bank by adding not-existing new precompiled program ({}). \
3397                Maybe, inconsistent program activation is detected on snapshot restore?",
3398            program_id
3399        );
3400
3401        // Add a bogus executable account, which will be loaded and ignored.
3402        let (lamports, rent_epoch) = self.inherit_specially_retained_account_fields(&None);
3403        let account = AccountSharedData::from(Account {
3404            lamports,
3405            owner,
3406            data: vec![],
3407            executable: true,
3408            rent_epoch,
3409        });
3410        self.store_account_and_update_capitalization(program_id, &account);
3411    }
3412
3413    pub fn set_rent_burn_percentage(&mut self, burn_percent: u8) {
3414        self.rent_collector.rent.burn_percent = burn_percent;
3415    }
3416
3417    pub fn set_hashes_per_tick(&mut self, hashes_per_tick: Option<u64>) {
3418        self.hashes_per_tick = hashes_per_tick;
3419    }
3420
3421    /// Return the last block hash registered.
3422    pub fn last_blockhash(&self) -> Hash {
3423        self.blockhash_queue.read().unwrap().last_hash()
3424    }
3425
3426    pub fn last_blockhash_and_lamports_per_signature(&self) -> (Hash, u64) {
3427        let blockhash_queue = self.blockhash_queue.read().unwrap();
3428        let last_hash = blockhash_queue.last_hash();
3429        let last_lamports_per_signature = blockhash_queue
3430            .get_lamports_per_signature(&last_hash)
3431            .unwrap(); // safe so long as the BlockhashQueue is consistent
3432        (last_hash, last_lamports_per_signature)
3433    }
3434
3435    pub fn is_blockhash_valid(&self, hash: &Hash) -> bool {
3436        let blockhash_queue = self.blockhash_queue.read().unwrap();
3437        blockhash_queue.is_hash_valid(hash)
3438    }
3439
3440    pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
3441        self.rent_collector.rent.minimum_balance(data_len).max(1)
3442    }
3443
3444    pub fn get_lamports_per_signature(&self) -> u64 {
3445        self.fee_rate_governor.lamports_per_signature
3446    }
3447
3448    pub fn get_lamports_per_signature_for_blockhash(&self, hash: &Hash) -> Option<u64> {
3449        let blockhash_queue = self.blockhash_queue.read().unwrap();
3450        blockhash_queue.get_lamports_per_signature(hash)
3451    }
3452
3453    #[deprecated(since = "1.9.0", note = "Please use `get_fee_for_message` instead")]
3454    pub fn get_fee_rate_governor(&self) -> &FeeRateGovernor {
3455        &self.fee_rate_governor
3456    }
3457
3458    pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> Option<u64> {
3459        let lamports_per_signature = {
3460            let blockhash_queue = self.blockhash_queue.read().unwrap();
3461            blockhash_queue.get_lamports_per_signature(message.recent_blockhash())
3462        }
3463        .or_else(|| {
3464            self.check_message_for_nonce(message)
3465                .and_then(|(address, account)| {
3466                    NoncePartial::new(address, account).lamports_per_signature()
3467                })
3468        })?;
3469        Some(Self::calculate_fee(
3470            message,
3471            lamports_per_signature,
3472            &self.fee_structure,
3473            self.feature_set
3474                .is_active(&add_set_compute_unit_price_ix::id()),
3475            self.feature_set
3476                .is_active(&use_default_units_in_fee_calculation::id()),
3477            self.enable_request_heap_frame_ix(),
3478        ))
3479    }
3480
3481    pub fn get_startup_verification_complete(&self) -> &Arc<AtomicBool> {
3482        &self
3483            .rc
3484            .accounts
3485            .accounts_db
3486            .verify_accounts_hash_in_bg
3487            .verified
3488    }
3489
3490    pub fn is_startup_verification_complete(&self) -> bool {
3491        self.rc
3492            .accounts
3493            .accounts_db
3494            .verify_accounts_hash_in_bg
3495            .check_complete()
3496    }
3497
3498    /// This can occur because it completed in the background
3499    /// or if the verification was run in the foreground.
3500    pub fn set_startup_verification_complete(&self) {
3501        self.rc
3502            .accounts
3503            .accounts_db
3504            .verify_accounts_hash_in_bg
3505            .verification_complete()
3506    }
3507
3508    pub fn get_fee_for_message_with_lamports_per_signature(
3509        &self,
3510        message: &SanitizedMessage,
3511        lamports_per_signature: u64,
3512    ) -> u64 {
3513        Self::calculate_fee(
3514            message,
3515            lamports_per_signature,
3516            &self.fee_structure,
3517            self.feature_set
3518                .is_active(&add_set_compute_unit_price_ix::id()),
3519            self.feature_set
3520                .is_active(&use_default_units_in_fee_calculation::id()),
3521            self.enable_request_heap_frame_ix(),
3522        )
3523    }
3524
3525    #[deprecated(
3526        since = "1.6.11",
3527        note = "Please use `get_blockhash_last_valid_block_height`"
3528    )]
3529    pub fn get_blockhash_last_valid_slot(&self, blockhash: &Hash) -> Option<Slot> {
3530        let blockhash_queue = self.blockhash_queue.read().unwrap();
3531        // This calculation will need to be updated to consider epoch boundaries if BlockhashQueue
3532        // length is made variable by epoch
3533        blockhash_queue
3534            .get_hash_age(blockhash)
3535            .map(|age| self.slot + blockhash_queue.get_max_age() as u64 - age)
3536    }
3537
3538    pub fn get_blockhash_last_valid_block_height(&self, blockhash: &Hash) -> Option<Slot> {
3539        let blockhash_queue = self.blockhash_queue.read().unwrap();
3540        // This calculation will need to be updated to consider epoch boundaries if BlockhashQueue
3541        // length is made variable by epoch
3542        blockhash_queue
3543            .get_hash_age(blockhash)
3544            .map(|age| self.block_height + blockhash_queue.get_max_age() as u64 - age)
3545    }
3546
3547    pub fn confirmed_last_blockhash(&self) -> Hash {
3548        const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
3549
3550        let parents = self.parents();
3551        if parents.is_empty() {
3552            self.last_blockhash()
3553        } else {
3554            let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
3555            parents[index].last_blockhash()
3556        }
3557    }
3558
3559    /// Forget all signatures. Useful for benchmarking.
3560    pub fn clear_signatures(&self) {
3561        self.status_cache.write().unwrap().clear();
3562    }
3563
3564    pub fn clear_slot_signatures(&self, slot: Slot) {
3565        self.status_cache.write().unwrap().clear_slot_entries(slot);
3566    }
3567
3568    fn update_transaction_statuses(
3569        &self,
3570        sanitized_txs: &[SanitizedTransaction],
3571        execution_results: &[TransactionExecutionResult],
3572    ) {
3573        let mut status_cache = self.status_cache.write().unwrap();
3574        assert_eq!(sanitized_txs.len(), execution_results.len());
3575        for (tx, execution_result) in sanitized_txs.iter().zip(execution_results) {
3576            if let Some(details) = execution_result.details() {
3577                // Add the message hash to the status cache to ensure that this message
3578                // won't be processed again with a different signature.
3579                status_cache.insert(
3580                    tx.message().recent_blockhash(),
3581                    tx.message_hash(),
3582                    self.slot(),
3583                    details.status.clone(),
3584                );
3585                // Add the transaction signature to the status cache so that transaction status
3586                // can be queried by transaction signature over RPC. In the future, this should
3587                // only be added for API nodes because voting validators don't need to do this.
3588                status_cache.insert(
3589                    tx.message().recent_blockhash(),
3590                    tx.signature(),
3591                    self.slot(),
3592                    details.status.clone(),
3593                );
3594            }
3595        }
3596    }
3597
3598    /// Register a new recent blockhash in the bank's recent blockhash queue. Called when a bank
3599    /// reaches its max tick height. Can be called by tests to get new blockhashes for transaction
3600    /// processing without advancing to a new bank slot.
3601    pub fn register_recent_blockhash(&self, blockhash: &Hash) {
3602        // Only acquire the write lock for the blockhash queue on block boundaries because
3603        // readers can starve this write lock acquisition and ticks would be slowed down too
3604        // much if the write lock is acquired for each tick.
3605        let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3606        w_blockhash_queue.register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3607        self.update_recent_blockhashes_locked(&w_blockhash_queue);
3608    }
3609
3610    /// Tell the bank which Entry IDs exist on the ledger. This function assumes subsequent calls
3611    /// correspond to later entries, and will boot the oldest ones once its internal cache is full.
3612    /// Once boot, the bank will reject transactions using that `hash`.
3613    ///
3614    /// This is NOT thread safe because if tick height is updated by two different threads, the
3615    /// block boundary condition could be missed.
3616    pub fn register_tick(&self, hash: &Hash) {
3617        assert!(
3618            !self.freeze_started(),
3619            "register_tick() working on a bank that is already frozen or is undergoing freezing!"
3620        );
3621
3622        inc_new_counter_debug!("bank-register_tick-registered", 1);
3623        if self.is_block_boundary(self.tick_height.load(Relaxed) + 1) {
3624            self.register_recent_blockhash(hash);
3625        }
3626
3627        // ReplayStage will start computing the accounts delta hash when it
3628        // detects the tick height has reached the boundary, so the system
3629        // needs to guarantee all account updates for the slot have been
3630        // committed before this tick height is incremented (like the blockhash
3631        // sysvar above)
3632        self.tick_height.fetch_add(1, Relaxed);
3633    }
3634
3635    pub fn is_complete(&self) -> bool {
3636        self.tick_height() == self.max_tick_height()
3637    }
3638
3639    pub fn is_block_boundary(&self, tick_height: u64) -> bool {
3640        if self
3641            .feature_set
3642            .is_active(&feature_set::fix_recent_blockhashes::id())
3643        {
3644            tick_height == self.max_tick_height
3645        } else {
3646            tick_height % self.ticks_per_slot == 0
3647        }
3648    }
3649
3650    /// Get the max number of accounts that a transaction may lock in this block
3651    pub fn get_transaction_account_lock_limit(&self) -> usize {
3652        if self
3653            .feature_set
3654            .is_active(&feature_set::increase_tx_account_lock_limit::id())
3655        {
3656            MAX_TX_ACCOUNT_LOCKS
3657        } else {
3658            64
3659        }
3660    }
3661
3662    /// Prepare a transaction batch from a list of legacy transactions. Used for tests only.
3663    pub fn prepare_batch_for_tests(&self, txs: Vec<Transaction>) -> TransactionBatch {
3664        let sanitized_txs = txs
3665            .into_iter()
3666            .map(SanitizedTransaction::from_transaction_for_tests)
3667            .collect::<Vec<_>>();
3668        let lock_results = self.rc.accounts.lock_accounts(
3669            sanitized_txs.iter(),
3670            self.get_transaction_account_lock_limit(),
3671        );
3672        TransactionBatch::new(lock_results, self, Cow::Owned(sanitized_txs))
3673    }
3674
3675    /// Prepare a transaction batch from a list of versioned transactions from
3676    /// an entry. Used for tests only.
3677    pub fn prepare_entry_batch(&self, txs: Vec<VersionedTransaction>) -> Result<TransactionBatch> {
3678        let sanitized_txs = txs
3679            .into_iter()
3680            .map(|tx| {
3681                SanitizedTransaction::try_create(
3682                    tx,
3683                    MessageHash::Compute,
3684                    None,
3685                    self,
3686                    self.feature_set
3687                        .is_active(&feature_set::require_static_program_ids_in_transaction::ID),
3688                )
3689            })
3690            .collect::<Result<Vec<_>>>()?;
3691        let lock_results = self.rc.accounts.lock_accounts(
3692            sanitized_txs.iter(),
3693            self.get_transaction_account_lock_limit(),
3694        );
3695        Ok(TransactionBatch::new(
3696            lock_results,
3697            self,
3698            Cow::Owned(sanitized_txs),
3699        ))
3700    }
3701
3702    /// Prepare a locked transaction batch from a list of sanitized transactions.
3703    pub fn prepare_sanitized_batch<'a, 'b>(
3704        &'a self,
3705        txs: &'b [SanitizedTransaction],
3706    ) -> TransactionBatch<'a, 'b> {
3707        let lock_results = self
3708            .rc
3709            .accounts
3710            .lock_accounts(txs.iter(), self.get_transaction_account_lock_limit());
3711        TransactionBatch::new(lock_results, self, Cow::Borrowed(txs))
3712    }
3713
3714    /// Prepare a locked transaction batch from a list of sanitized transactions, and their cost
3715    /// limited packing status
3716    pub fn prepare_sanitized_batch_with_results<'a, 'b>(
3717        &'a self,
3718        transactions: &'b [SanitizedTransaction],
3719        transaction_results: impl Iterator<Item = &'b Result<()>>,
3720    ) -> TransactionBatch<'a, 'b> {
3721        // this lock_results could be: Ok, AccountInUse, WouldExceedBlockMaxLimit or WouldExceedAccountMaxLimit
3722        let lock_results = self.rc.accounts.lock_accounts_with_results(
3723            transactions.iter(),
3724            transaction_results,
3725            self.get_transaction_account_lock_limit(),
3726        );
3727        TransactionBatch::new(lock_results, self, Cow::Borrowed(transactions))
3728    }
3729
3730    /// Prepare a transaction batch without locking accounts for transaction simulation.
3731    pub(crate) fn prepare_simulation_batch<'a>(
3732        &'a self,
3733        transaction: SanitizedTransaction,
3734    ) -> TransactionBatch<'a, '_> {
3735        let lock_result = transaction
3736            .get_account_locks(self.get_transaction_account_lock_limit())
3737            .map(|_| ());
3738        let mut batch =
3739            TransactionBatch::new(vec![lock_result], self, Cow::Owned(vec![transaction]));
3740        batch.set_needs_unlock(false);
3741        batch
3742    }
3743
3744    /// Run transactions against a frozen bank without committing the results
3745    pub fn simulate_transaction(
3746        &self,
3747        transaction: SanitizedTransaction,
3748    ) -> TransactionSimulationResult {
3749        assert!(self.is_frozen(), "simulation bank must be frozen");
3750
3751        self.simulate_transaction_unchecked(transaction)
3752    }
3753
3754    /// Run transactions against a bank without committing the results; does not check if the bank
3755    /// is frozen, enabling use in single-Bank test frameworks
3756    pub fn simulate_transaction_unchecked(
3757        &self,
3758        transaction: SanitizedTransaction,
3759    ) -> TransactionSimulationResult {
3760        let account_keys = transaction.message().account_keys();
3761        let number_of_accounts = account_keys.len();
3762        let account_overrides = self.get_account_overrides_for_simulation(&account_keys);
3763        let batch = self.prepare_simulation_batch(transaction);
3764        let mut timings = ExecuteTimings::default();
3765
3766        let LoadAndExecuteTransactionsOutput {
3767            loaded_transactions,
3768            mut execution_results,
3769            ..
3770        } = self.load_and_execute_transactions(
3771            &batch,
3772            // After simulation, transactions will need to be forwarded to the leader
3773            // for processing. During forwarding, the transaction could expire if the
3774            // delay is not accounted for.
3775            MAX_PROCESSING_AGE - MAX_TRANSACTION_FORWARDING_DELAY,
3776            false,
3777            true,
3778            true,
3779            &mut timings,
3780            Some(&account_overrides),
3781            None,
3782        );
3783
3784        let post_simulation_accounts = loaded_transactions
3785            .into_iter()
3786            .next()
3787            .unwrap()
3788            .0
3789            .ok()
3790            .map(|loaded_transaction| {
3791                loaded_transaction
3792                    .accounts
3793                    .into_iter()
3794                    .take(number_of_accounts)
3795                    .collect::<Vec<_>>()
3796            })
3797            .unwrap_or_default();
3798
3799        let units_consumed = timings
3800            .details
3801            .per_program_timings
3802            .iter()
3803            .fold(0, |acc: u64, (_, program_timing)| {
3804                acc.saturating_add(program_timing.accumulated_units)
3805            });
3806
3807        debug!("simulate_transaction: {:?}", timings);
3808
3809        let execution_result = execution_results.pop().unwrap();
3810        let flattened_result = execution_result.flattened_result();
3811        let (logs, return_data) = match execution_result {
3812            TransactionExecutionResult::Executed { details, .. } => {
3813                (details.log_messages, details.return_data)
3814            }
3815            TransactionExecutionResult::NotExecuted(_) => (None, None),
3816        };
3817        let logs = logs.unwrap_or_default();
3818
3819        TransactionSimulationResult {
3820            result: flattened_result,
3821            logs,
3822            post_simulation_accounts,
3823            units_consumed,
3824            return_data,
3825        }
3826    }
3827
3828    fn get_account_overrides_for_simulation(&self, account_keys: &AccountKeys) -> AccountOverrides {
3829        let mut account_overrides = AccountOverrides::default();
3830        let slot_history_id = sysvar::slot_history::id();
3831        if account_keys.iter().any(|pubkey| *pubkey == slot_history_id) {
3832            let current_account = self.get_account_with_fixed_root(&slot_history_id);
3833            let slot_history = current_account
3834                .as_ref()
3835                .map(|account| from_account::<SlotHistory, _>(account).unwrap())
3836                .unwrap_or_default();
3837            if slot_history.check(self.slot()) == Check::Found {
3838                let ancestors = Ancestors::from(self.proper_ancestors().collect::<Vec<_>>());
3839                if let Some((account, _)) =
3840                    self.load_slow_with_fixed_root(&ancestors, &slot_history_id)
3841                {
3842                    account_overrides.set_slot_history(Some(account));
3843                }
3844            }
3845        }
3846        account_overrides
3847    }
3848
3849    pub fn unlock_accounts(&self, batch: &mut TransactionBatch) {
3850        if batch.needs_unlock() {
3851            batch.set_needs_unlock(false);
3852            self.rc
3853                .accounts
3854                .unlock_accounts(batch.sanitized_transactions().iter(), batch.lock_results())
3855        }
3856    }
3857
3858    pub fn remove_unrooted_slots(&self, slots: &[(Slot, BankId)]) {
3859        self.rc.accounts.accounts_db.remove_unrooted_slots(slots)
3860    }
3861
3862    pub fn set_shrink_paths(&self, paths: Vec<PathBuf>) {
3863        self.rc.accounts.accounts_db.set_shrink_paths(paths);
3864    }
3865
3866    fn check_age<'a>(
3867        &self,
3868        txs: impl Iterator<Item = &'a SanitizedTransaction>,
3869        lock_results: &[Result<()>],
3870        max_age: usize,
3871        error_counters: &mut TransactionErrorMetrics,
3872    ) -> Vec<TransactionCheckResult> {
3873        let hash_queue = self.blockhash_queue.read().unwrap();
3874        let last_blockhash = hash_queue.last_hash();
3875        let next_durable_nonce = DurableNonce::from_blockhash(&last_blockhash);
3876
3877        txs.zip(lock_results)
3878            .map(|(tx, lock_res)| match lock_res {
3879                Ok(()) => {
3880                    let recent_blockhash = tx.message().recent_blockhash();
3881                    if hash_queue.is_hash_valid_for_age(recent_blockhash, max_age) {
3882                        (Ok(()), None)
3883                    } else if let Some((address, account)) =
3884                        self.check_transaction_for_nonce(tx, &next_durable_nonce)
3885                    {
3886                        (Ok(()), Some(NoncePartial::new(address, account)))
3887                    } else {
3888                        error_counters.blockhash_not_found += 1;
3889                        (Err(TransactionError::BlockhashNotFound), None)
3890                    }
3891                }
3892                Err(e) => (Err(e.clone()), None),
3893            })
3894            .collect()
3895    }
3896
3897    fn is_transaction_already_processed(
3898        &self,
3899        sanitized_tx: &SanitizedTransaction,
3900        status_cache: &BankStatusCache,
3901    ) -> bool {
3902        let key = sanitized_tx.message_hash();
3903        let transaction_blockhash = sanitized_tx.message().recent_blockhash();
3904        status_cache
3905            .get_status(key, transaction_blockhash, &self.ancestors)
3906            .is_some()
3907    }
3908
3909    fn check_status_cache(
3910        &self,
3911        sanitized_txs: &[SanitizedTransaction],
3912        lock_results: Vec<TransactionCheckResult>,
3913        error_counters: &mut TransactionErrorMetrics,
3914    ) -> Vec<TransactionCheckResult> {
3915        let rcache = self.status_cache.read().unwrap();
3916        sanitized_txs
3917            .iter()
3918            .zip(lock_results)
3919            .map(|(sanitized_tx, (lock_result, nonce))| {
3920                if lock_result.is_ok()
3921                    && self.is_transaction_already_processed(sanitized_tx, &rcache)
3922                {
3923                    error_counters.already_processed += 1;
3924                    return (Err(TransactionError::AlreadyProcessed), None);
3925                }
3926
3927                (lock_result, nonce)
3928            })
3929            .collect()
3930    }
3931
3932    pub fn get_hash_age(&self, hash: &Hash) -> Option<u64> {
3933        self.blockhash_queue.read().unwrap().get_hash_age(hash)
3934    }
3935
3936    pub fn is_hash_valid_for_age(&self, hash: &Hash, max_age: usize) -> bool {
3937        self.blockhash_queue
3938            .read()
3939            .unwrap()
3940            .is_hash_valid_for_age(hash, max_age)
3941    }
3942
3943    fn check_message_for_nonce(&self, message: &SanitizedMessage) -> Option<TransactionAccount> {
3944        let nonce_address = message.get_durable_nonce()?;
3945        let nonce_account = self.get_account_with_fixed_root(nonce_address)?;
3946        let nonce_data =
3947            nonce_account::verify_nonce_account(&nonce_account, message.recent_blockhash())?;
3948
3949        let nonce_is_authorized = message
3950            .get_ix_signers(NONCED_TX_MARKER_IX_INDEX as usize)
3951            .any(|signer| signer == &nonce_data.authority);
3952        if !nonce_is_authorized {
3953            return None;
3954        }
3955
3956        Some((*nonce_address, nonce_account))
3957    }
3958
3959    fn check_transaction_for_nonce(
3960        &self,
3961        tx: &SanitizedTransaction,
3962        next_durable_nonce: &DurableNonce,
3963    ) -> Option<TransactionAccount> {
3964        let nonce_is_advanceable = tx.message().recent_blockhash() != next_durable_nonce.as_hash();
3965        if nonce_is_advanceable {
3966            self.check_message_for_nonce(tx.message())
3967        } else {
3968            None
3969        }
3970    }
3971
3972    pub fn check_transactions(
3973        &self,
3974        sanitized_txs: &[SanitizedTransaction],
3975        lock_results: &[Result<()>],
3976        max_age: usize,
3977        error_counters: &mut TransactionErrorMetrics,
3978    ) -> Vec<TransactionCheckResult> {
3979        let age_results =
3980            self.check_age(sanitized_txs.iter(), lock_results, max_age, error_counters);
3981        self.check_status_cache(sanitized_txs, age_results, error_counters)
3982    }
3983
3984    pub fn collect_balances(&self, batch: &TransactionBatch) -> TransactionBalances {
3985        let mut balances: TransactionBalances = vec![];
3986        for transaction in batch.sanitized_transactions() {
3987            let mut transaction_balances: Vec<u64> = vec![];
3988            for account_key in transaction.message().account_keys().iter() {
3989                transaction_balances.push(self.get_balance(account_key));
3990            }
3991            balances.push(transaction_balances);
3992        }
3993        balances
3994    }
3995
3996    /// Get any cached executors needed by the transaction
3997    fn get_executors(&self, accounts: &[TransactionAccount]) -> Rc<RefCell<Executors>> {
3998        let executable_keys: Vec<_> = accounts
3999            .iter()
4000            .filter_map(|(key, account)| {
4001                if account.executable() && !native_loader::check_id(account.owner()) {
4002                    Some(key)
4003                } else {
4004                    None
4005                }
4006            })
4007            .collect();
4008
4009        if executable_keys.is_empty() {
4010            return Rc::new(RefCell::new(Executors::default()));
4011        }
4012
4013        let executors = {
4014            let cache = self.cached_executors.read().unwrap();
4015            executable_keys
4016                .into_iter()
4017                .filter_map(|key| {
4018                    cache
4019                        .get(key)
4020                        .map(|executor| (*key, TransactionExecutor::new_cached(executor)))
4021                })
4022                .collect()
4023        };
4024
4025        Rc::new(RefCell::new(executors))
4026    }
4027
4028    /// Add executors back to the bank's cache if they were missing and not updated
4029    fn store_missing_executors(&self, executors: &RefCell<Executors>) {
4030        self.store_executors_internal(executors, |e| e.is_missing())
4031    }
4032
4033    /// Add updated executors back to the bank's cache
4034    fn store_updated_executors(&self, executors: &RefCell<Executors>) {
4035        self.store_executors_internal(executors, |e| e.is_updated())
4036    }
4037
4038    /// Helper to write a selection of executors to the bank's cache
4039    fn store_executors_internal(
4040        &self,
4041        executors: &RefCell<Executors>,
4042        selector: impl Fn(&TransactionExecutor) -> bool,
4043    ) {
4044        let executors = executors.borrow();
4045        let dirty_executors: Vec<_> = executors
4046            .iter()
4047            .filter_map(|(key, executor)| selector(executor).then(|| (key, executor.get())))
4048            .collect();
4049
4050        if !dirty_executors.is_empty() {
4051            self.cached_executors.write().unwrap().put(&dirty_executors);
4052        }
4053    }
4054
4055    /// Remove an executor from the bank's cache
4056    fn remove_executor(&self, pubkey: &Pubkey) {
4057        let _ = self.cached_executors.write().unwrap().remove(pubkey);
4058    }
4059
4060    pub fn clear_executors(&self) {
4061        self.cached_executors.write().unwrap().clear();
4062    }
4063
4064    /// Execute a transaction using the provided loaded accounts and update
4065    /// the executors cache if the transaction was successful.
4066    #[allow(clippy::too_many_arguments)]
4067    fn execute_loaded_transaction(
4068        &self,
4069        tx: &SanitizedTransaction,
4070        loaded_transaction: &mut LoadedTransaction,
4071        compute_budget: ComputeBudget,
4072        durable_nonce_fee: Option<DurableNonceFee>,
4073        enable_cpi_recording: bool,
4074        enable_log_recording: bool,
4075        enable_return_data_recording: bool,
4076        timings: &mut ExecuteTimings,
4077        error_counters: &mut TransactionErrorMetrics,
4078        log_messages_bytes_limit: Option<usize>,
4079    ) -> TransactionExecutionResult {
4080        let mut get_executors_time = Measure::start("get_executors_time");
4081        let executors = self.get_executors(&loaded_transaction.accounts);
4082        get_executors_time.stop();
4083        saturating_add_assign!(
4084            timings.execute_accessories.get_executors_us,
4085            get_executors_time.as_us()
4086        );
4087
4088        let prev_accounts_data_len = self.load_accounts_data_size();
4089        let transaction_accounts = std::mem::take(&mut loaded_transaction.accounts);
4090        let mut transaction_context = TransactionContext::new(
4091            transaction_accounts,
4092            if self
4093                .feature_set
4094                .is_active(&enable_early_verification_of_account_modifications::id())
4095            {
4096                Some(self.rent_collector.rent)
4097            } else {
4098                None
4099            },
4100            compute_budget.max_invoke_depth.saturating_add(1),
4101            tx.message().instructions().len(),
4102        );
4103
4104        let pre_account_state_info =
4105            self.get_transaction_account_state_info(&transaction_context, tx.message());
4106
4107        let log_collector = if enable_log_recording {
4108            match log_messages_bytes_limit {
4109                None => Some(LogCollector::new_ref()),
4110                Some(log_messages_bytes_limit) => Some(LogCollector::new_ref_with_limit(Some(
4111                    log_messages_bytes_limit,
4112                ))),
4113            }
4114        } else {
4115            None
4116        };
4117
4118        let (blockhash, lamports_per_signature) = self.last_blockhash_and_lamports_per_signature();
4119
4120        let mut executed_units = 0u64;
4121
4122        let mut process_message_time = Measure::start("process_message_time");
4123        let process_result = MessageProcessor::process_message(
4124            &self.builtin_programs.vec,
4125            tx.message(),
4126            &loaded_transaction.program_indices,
4127            &mut transaction_context,
4128            self.rent_collector.rent,
4129            log_collector.clone(),
4130            executors.clone(),
4131            self.feature_set.clone(),
4132            compute_budget,
4133            timings,
4134            &*self.sysvar_cache.read().unwrap(),
4135            blockhash,
4136            lamports_per_signature,
4137            prev_accounts_data_len,
4138            &mut executed_units,
4139        );
4140        process_message_time.stop();
4141
4142        saturating_add_assign!(
4143            timings.execute_accessories.process_message_us,
4144            process_message_time.as_us()
4145        );
4146
4147        let mut store_missing_executors_time = Measure::start("store_missing_executors_time");
4148        self.store_missing_executors(&executors);
4149        store_missing_executors_time.stop();
4150        saturating_add_assign!(
4151            timings.execute_accessories.update_executors_us,
4152            store_missing_executors_time.as_us()
4153        );
4154
4155        let status = process_result
4156            .and_then(|info| {
4157                let post_account_state_info =
4158                    self.get_transaction_account_state_info(&transaction_context, tx.message());
4159                self.verify_transaction_account_state_changes(
4160                    &pre_account_state_info,
4161                    &post_account_state_info,
4162                    &transaction_context,
4163                )
4164                .map(|_| info)
4165            })
4166            .map_err(|err| {
4167                match err {
4168                    TransactionError::InvalidRentPayingAccount
4169                    | TransactionError::InsufficientFundsForRent { .. } => {
4170                        error_counters.invalid_rent_paying_account += 1;
4171                    }
4172                    TransactionError::InvalidAccountIndex => {
4173                        error_counters.invalid_account_index += 1;
4174                    }
4175                    _ => {
4176                        error_counters.instruction_error += 1;
4177                    }
4178                }
4179                err
4180            });
4181        let mut accounts_data_len_delta = status
4182            .as_ref()
4183            .map_or(0, |info| info.accounts_data_len_delta);
4184        let status = status.map(|_| ());
4185
4186        let log_messages: Option<TransactionLogMessages> =
4187            log_collector.and_then(|log_collector| {
4188                Rc::try_unwrap(log_collector)
4189                    .map(|log_collector| log_collector.into_inner().into())
4190                    .ok()
4191            });
4192
4193        let ExecutionRecord {
4194            accounts,
4195            instruction_trace,
4196            mut return_data,
4197            changed_account_count,
4198            total_size_of_all_accounts,
4199            total_size_of_touched_accounts,
4200            accounts_resize_delta,
4201        } = transaction_context.into();
4202        loaded_transaction.accounts = accounts;
4203        if self
4204            .feature_set
4205            .is_active(&enable_early_verification_of_account_modifications::id())
4206        {
4207            saturating_add_assign!(
4208                timings.details.total_account_count,
4209                loaded_transaction.accounts.len() as u64
4210            );
4211            saturating_add_assign!(timings.details.changed_account_count, changed_account_count);
4212            saturating_add_assign!(
4213                timings.details.total_data_size,
4214                total_size_of_all_accounts as usize
4215            );
4216            saturating_add_assign!(
4217                timings.details.data_size_changed,
4218                total_size_of_touched_accounts as usize
4219            );
4220            accounts_data_len_delta = status.as_ref().map_or(0, |_| accounts_resize_delta);
4221        }
4222
4223        let inner_instructions = if enable_cpi_recording {
4224            Some(inner_instructions_list_from_instruction_trace(
4225                &instruction_trace,
4226            ))
4227        } else {
4228            None
4229        };
4230
4231        let return_data = if enable_return_data_recording {
4232            if let Some(end_index) = return_data.data.iter().rposition(|&x| x != 0) {
4233                let end_index = end_index.saturating_add(1);
4234                return_data.data.truncate(end_index);
4235                Some(return_data)
4236            } else {
4237                None
4238            }
4239        } else {
4240            None
4241        };
4242
4243        TransactionExecutionResult::Executed {
4244            details: TransactionExecutionDetails {
4245                status,
4246                log_messages,
4247                inner_instructions,
4248                durable_nonce_fee,
4249                return_data,
4250                executed_units,
4251                accounts_data_len_delta,
4252            },
4253            executors,
4254        }
4255    }
4256
4257    // A cluster specific feature gate, when not activated it keeps v1.13 behavior in mainnet-beta;
4258    // once activated for v1.14+, it allows compute_budget::request_heap_frame and
4259    // compute_budget::set_compute_unit_price co-exist in same transaction.
4260    fn enable_request_heap_frame_ix(&self) -> bool {
4261        self.feature_set
4262            .is_active(&enable_request_heap_frame_ix::id())
4263            || self.cluster_type() != ClusterType::MainnetBeta
4264    }
4265
4266    #[allow(clippy::type_complexity)]
4267    pub fn load_and_execute_transactions(
4268        &self,
4269        batch: &TransactionBatch,
4270        max_age: usize,
4271        enable_cpi_recording: bool,
4272        enable_log_recording: bool,
4273        enable_return_data_recording: bool,
4274        timings: &mut ExecuteTimings,
4275        account_overrides: Option<&AccountOverrides>,
4276        log_messages_bytes_limit: Option<usize>,
4277    ) -> LoadAndExecuteTransactionsOutput {
4278        let sanitized_txs = batch.sanitized_transactions();
4279        debug!("processing transactions: {}", sanitized_txs.len());
4280        inc_new_counter_info!("bank-process_transactions", sanitized_txs.len());
4281        let mut error_counters = TransactionErrorMetrics::default();
4282
4283        let retryable_transaction_indexes: Vec<_> = batch
4284            .lock_results()
4285            .iter()
4286            .enumerate()
4287            .filter_map(|(index, res)| match res {
4288                // following are retryable errors
4289                Err(TransactionError::AccountInUse) => {
4290                    error_counters.account_in_use += 1;
4291                    Some(index)
4292                }
4293                Err(TransactionError::WouldExceedMaxBlockCostLimit) => {
4294                    error_counters.would_exceed_max_block_cost_limit += 1;
4295                    Some(index)
4296                }
4297                Err(TransactionError::WouldExceedMaxVoteCostLimit) => {
4298                    error_counters.would_exceed_max_vote_cost_limit += 1;
4299                    Some(index)
4300                }
4301                Err(TransactionError::WouldExceedMaxAccountCostLimit) => {
4302                    error_counters.would_exceed_max_account_cost_limit += 1;
4303                    Some(index)
4304                }
4305                Err(TransactionError::WouldExceedAccountDataBlockLimit) => {
4306                    error_counters.would_exceed_account_data_block_limit += 1;
4307                    Some(index)
4308                }
4309                // following are non-retryable errors
4310                Err(TransactionError::TooManyAccountLocks) => {
4311                    error_counters.too_many_account_locks += 1;
4312                    None
4313                }
4314                Err(_) => None,
4315                Ok(_) => None,
4316            })
4317            .collect();
4318
4319        let mut check_time = Measure::start("check_transactions");
4320        let check_results = self.check_transactions(
4321            sanitized_txs,
4322            batch.lock_results(),
4323            max_age,
4324            &mut error_counters,
4325        );
4326        check_time.stop();
4327
4328        let mut load_time = Measure::start("accounts_load");
4329        let mut loaded_transactions = self.rc.accounts.load_accounts(
4330            &self.ancestors,
4331            sanitized_txs,
4332            check_results,
4333            &self.blockhash_queue.read().unwrap(),
4334            &mut error_counters,
4335            &self.rent_collector,
4336            &self.feature_set,
4337            &self.fee_structure,
4338            account_overrides,
4339        );
4340        load_time.stop();
4341
4342        let mut execution_time = Measure::start("execution_time");
4343        let mut signature_count: u64 = 0;
4344
4345        let execution_results: Vec<TransactionExecutionResult> = loaded_transactions
4346            .iter_mut()
4347            .zip(sanitized_txs.iter())
4348            .map(|(accs, tx)| match accs {
4349                (Err(e), _nonce) => TransactionExecutionResult::NotExecuted(e.clone()),
4350                (Ok(loaded_transaction), nonce) => {
4351                    let mut feature_set_clone_time = Measure::start("feature_set_clone");
4352                    let feature_set = self.feature_set.clone();
4353                    feature_set_clone_time.stop();
4354                    saturating_add_assign!(
4355                        timings.execute_accessories.feature_set_clone_us,
4356                        feature_set_clone_time.as_us()
4357                    );
4358
4359                    let compute_budget = if let Some(compute_budget) = self.compute_budget {
4360                        compute_budget
4361                    } else {
4362                        let mut compute_budget =
4363                            ComputeBudget::new(compute_budget::MAX_COMPUTE_UNIT_LIMIT as u64);
4364
4365                        let mut compute_budget_process_transaction_time =
4366                            Measure::start("compute_budget_process_transaction_time");
4367                        let process_transaction_result = compute_budget.process_instructions(
4368                            tx.message().program_instructions_iter(),
4369                            feature_set.is_active(&default_units_per_instruction::id()),
4370                            feature_set.is_active(&add_set_compute_unit_price_ix::id()),
4371                            true, // don't reject txs that use request heap size ix
4372                        );
4373                        compute_budget_process_transaction_time.stop();
4374                        saturating_add_assign!(
4375                            timings
4376                                .execute_accessories
4377                                .compute_budget_process_transaction_us,
4378                            compute_budget_process_transaction_time.as_us()
4379                        );
4380                        if let Err(err) = process_transaction_result {
4381                            return TransactionExecutionResult::NotExecuted(err);
4382                        }
4383                        compute_budget
4384                    };
4385
4386                    self.execute_loaded_transaction(
4387                        tx,
4388                        loaded_transaction,
4389                        compute_budget,
4390                        nonce.as_ref().map(DurableNonceFee::from),
4391                        enable_cpi_recording,
4392                        enable_log_recording,
4393                        enable_return_data_recording,
4394                        timings,
4395                        &mut error_counters,
4396                        log_messages_bytes_limit,
4397                    )
4398                }
4399            })
4400            .collect();
4401
4402        execution_time.stop();
4403
4404        debug!(
4405            "check: {}us load: {}us execute: {}us txs_len={}",
4406            check_time.as_us(),
4407            load_time.as_us(),
4408            execution_time.as_us(),
4409            sanitized_txs.len(),
4410        );
4411
4412        timings.saturating_add_in_place(ExecuteTimingType::CheckUs, check_time.as_us());
4413        timings.saturating_add_in_place(ExecuteTimingType::LoadUs, load_time.as_us());
4414        timings.saturating_add_in_place(ExecuteTimingType::ExecuteUs, execution_time.as_us());
4415
4416        let mut executed_transactions_count: usize = 0;
4417        let mut executed_with_successful_result_count: usize = 0;
4418        let err_count = &mut error_counters.total;
4419        let transaction_log_collector_config =
4420            self.transaction_log_collector_config.read().unwrap();
4421
4422        let mut collect_logs_time = Measure::start("collect_logs_time");
4423        for (execution_result, tx) in execution_results.iter().zip(sanitized_txs) {
4424            if let Some(debug_keys) = &self.transaction_debug_keys {
4425                for key in tx.message().account_keys().iter() {
4426                    if debug_keys.contains(key) {
4427                        let result = execution_result.flattened_result();
4428                        info!("slot: {} result: {:?} tx: {:?}", self.slot, result, tx);
4429                        break;
4430                    }
4431                }
4432            }
4433
4434            if execution_result.was_executed() // Skip log collection for unprocessed transactions
4435                && transaction_log_collector_config.filter != TransactionLogCollectorFilter::None
4436            {
4437                let mut filtered_mentioned_addresses = Vec::new();
4438                if !transaction_log_collector_config
4439                    .mentioned_addresses
4440                    .is_empty()
4441                {
4442                    for key in tx.message().account_keys().iter() {
4443                        if transaction_log_collector_config
4444                            .mentioned_addresses
4445                            .contains(key)
4446                        {
4447                            filtered_mentioned_addresses.push(*key);
4448                        }
4449                    }
4450                }
4451
4452                let is_vote = vote_parser::is_simple_vote_transaction(tx);
4453                let store = match transaction_log_collector_config.filter {
4454                    TransactionLogCollectorFilter::All => {
4455                        !is_vote || !filtered_mentioned_addresses.is_empty()
4456                    }
4457                    TransactionLogCollectorFilter::AllWithVotes => true,
4458                    TransactionLogCollectorFilter::None => false,
4459                    TransactionLogCollectorFilter::OnlyMentionedAddresses => {
4460                        !filtered_mentioned_addresses.is_empty()
4461                    }
4462                };
4463
4464                if store {
4465                    if let Some(TransactionExecutionDetails {
4466                        status,
4467                        log_messages: Some(log_messages),
4468                        ..
4469                    }) = execution_result.details()
4470                    {
4471                        let mut transaction_log_collector =
4472                            self.transaction_log_collector.write().unwrap();
4473                        let transaction_log_index = transaction_log_collector.logs.len();
4474
4475                        transaction_log_collector.logs.push(TransactionLogInfo {
4476                            signature: *tx.signature(),
4477                            result: status.clone(),
4478                            is_vote,
4479                            log_messages: log_messages.clone(),
4480                        });
4481                        for key in filtered_mentioned_addresses.into_iter() {
4482                            transaction_log_collector
4483                                .mentioned_address_map
4484                                .entry(key)
4485                                .or_default()
4486                                .push(transaction_log_index);
4487                        }
4488                    }
4489                }
4490            }
4491
4492            if execution_result.was_executed() {
4493                // Signature count must be accumulated only if the transaction
4494                // is executed, otherwise a mismatched count between banking and
4495                // replay could occur
4496                signature_count += u64::from(tx.message().header().num_required_signatures);
4497                executed_transactions_count += 1;
4498            }
4499
4500            match execution_result.flattened_result() {
4501                Ok(()) => {
4502                    executed_with_successful_result_count += 1;
4503                }
4504                Err(err) => {
4505                    if *err_count == 0 {
4506                        debug!("tx error: {:?} {:?}", err, tx);
4507                    }
4508                    *err_count += 1;
4509                }
4510            }
4511        }
4512        collect_logs_time.stop();
4513        timings
4514            .saturating_add_in_place(ExecuteTimingType::CollectLogsUs, collect_logs_time.as_us());
4515
4516        if *err_count > 0 {
4517            debug!(
4518                "{} errors of {} txs",
4519                *err_count,
4520                *err_count + executed_with_successful_result_count
4521            );
4522        }
4523        LoadAndExecuteTransactionsOutput {
4524            loaded_transactions,
4525            execution_results,
4526            retryable_transaction_indexes,
4527            executed_transactions_count,
4528            executed_with_successful_result_count,
4529            signature_count,
4530            error_counters,
4531        }
4532    }
4533
4534    /// The maximum allowed size, in bytes, of the accounts data
4535    pub fn accounts_data_size_limit(&self) -> u64 {
4536        MAX_ACCOUNTS_DATA_LEN
4537    }
4538
4539    /// Load the accounts data size, in bytes
4540    pub fn load_accounts_data_size(&self) -> u64 {
4541        // Mixed integer ops currently not stable, so copying the impl.
4542        // Copied from: https://github.com/a1phyr/rust/blob/47edde1086412b36e9efd6098b191ec15a2a760a/library/core/src/num/uint_macros.rs#L1039-L1048
4543        fn saturating_add_signed(lhs: u64, rhs: i64) -> u64 {
4544            let (res, overflow) = lhs.overflowing_add(rhs as u64);
4545            if overflow == (rhs < 0) {
4546                res
4547            } else if overflow {
4548                u64::MAX
4549            } else {
4550                u64::MIN
4551            }
4552        }
4553        saturating_add_signed(
4554            self.accounts_data_size_initial,
4555            self.load_accounts_data_size_delta(),
4556        )
4557    }
4558
4559    /// Load the change in accounts data size in this Bank, in bytes
4560    pub fn load_accounts_data_size_delta(&self) -> i64 {
4561        let delta_on_chain = self.load_accounts_data_size_delta_on_chain();
4562        let delta_off_chain = self.load_accounts_data_size_delta_off_chain();
4563        delta_on_chain.saturating_add(delta_off_chain)
4564    }
4565
4566    /// Load the change in accounts data size in this Bank, in bytes, from on-chain events
4567    /// i.e. transactions
4568    pub fn load_accounts_data_size_delta_on_chain(&self) -> i64 {
4569        self.accounts_data_size_delta_on_chain.load(Acquire)
4570    }
4571
4572    /// Load the change in accounts data size in this Bank, in bytes, from off-chain events
4573    /// i.e. rent collection
4574    pub fn load_accounts_data_size_delta_off_chain(&self) -> i64 {
4575        self.accounts_data_size_delta_off_chain.load(Acquire)
4576    }
4577
4578    /// Update the accounts data size delta from on-chain events by adding `amount`.
4579    /// The arithmetic saturates.
4580    fn update_accounts_data_size_delta_on_chain(&self, amount: i64) {
4581        if amount == 0 {
4582            return;
4583        }
4584
4585        self.accounts_data_size_delta_on_chain
4586            .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_on_chain| {
4587                Some(accounts_data_size_delta_on_chain.saturating_add(amount))
4588            })
4589            // SAFETY: unwrap() is safe since our update fn always returns `Some`
4590            .unwrap();
4591    }
4592
4593    /// Update the accounts data size delta from off-chain events by adding `amount`.
4594    /// The arithmetic saturates.
4595    fn update_accounts_data_size_delta_off_chain(&self, amount: i64) {
4596        if amount == 0 {
4597            return;
4598        }
4599
4600        self.accounts_data_size_delta_off_chain
4601            .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_off_chain| {
4602                Some(accounts_data_size_delta_off_chain.saturating_add(amount))
4603            })
4604            // SAFETY: unwrap() is safe since our update fn always returns `Some`
4605            .unwrap();
4606    }
4607
4608    /// Calculate the data size delta and update the off-chain accounts data size delta
4609    fn calculate_and_update_accounts_data_size_delta_off_chain(
4610        &self,
4611        old_data_size: usize,
4612        new_data_size: usize,
4613    ) {
4614        let data_size_delta = calculate_data_size_delta(old_data_size, new_data_size);
4615        self.update_accounts_data_size_delta_off_chain(data_size_delta);
4616    }
4617
4618    /// Set the initial accounts data size
4619    /// NOTE: This fn is *ONLY FOR TESTS*
4620    pub fn set_accounts_data_size_initial_for_tests(&mut self, amount: u64) {
4621        self.accounts_data_size_initial = amount;
4622    }
4623
4624    /// Update the accounts data size off-chain delta
4625    /// NOTE: This fn is *ONLY FOR TESTS*
4626    pub fn update_accounts_data_size_delta_off_chain_for_tests(&self, amount: i64) {
4627        self.update_accounts_data_size_delta_off_chain(amount)
4628    }
4629
4630    fn get_num_signatures_in_message(message: &SanitizedMessage) -> u64 {
4631        let mut num_signatures = u64::from(message.header().num_required_signatures);
4632        // This next part is really calculating the number of pre-processor
4633        // operations being done and treating them like a signature
4634        for (program_id, instruction) in message.program_instructions_iter() {
4635            if secp256k1_program::check_id(program_id) || ed25519_program::check_id(program_id) {
4636                if let Some(num_verifies) = instruction.data.first() {
4637                    num_signatures = num_signatures.saturating_add(u64::from(*num_verifies));
4638                }
4639            }
4640        }
4641        num_signatures
4642    }
4643
4644    fn get_num_write_locks_in_message(message: &SanitizedMessage) -> u64 {
4645        message
4646            .account_keys()
4647            .len()
4648            .saturating_sub(message.num_readonly_accounts()) as u64
4649    }
4650
4651    /// Calculate fee for `SanitizedMessage`
4652    pub fn calculate_fee(
4653        message: &SanitizedMessage,
4654        lamports_per_signature: u64,
4655        fee_structure: &FeeStructure,
4656        support_set_compute_unit_price_ix: bool,
4657        use_default_units_per_instruction: bool,
4658        enable_request_heap_frame_ix: bool,
4659    ) -> u64 {
4660        // Fee based on compute units and signatures
4661        const BASE_CONGESTION: f64 = 5_000.0;
4662        let current_congestion = BASE_CONGESTION.max(lamports_per_signature as f64);
4663        let congestion_multiplier = if lamports_per_signature == 0 {
4664            0.0 // test only
4665        } else {
4666            BASE_CONGESTION / current_congestion
4667        };
4668
4669        let mut compute_budget = ComputeBudget::default();
4670        let prioritization_fee_details = compute_budget
4671            .process_instructions(
4672                message.program_instructions_iter(),
4673                use_default_units_per_instruction,
4674                support_set_compute_unit_price_ix,
4675                enable_request_heap_frame_ix,
4676            )
4677            .unwrap_or_default();
4678        let prioritization_fee = prioritization_fee_details.get_fee();
4679        let signature_fee = Self::get_num_signatures_in_message(message)
4680            .saturating_mul(fee_structure.lamports_per_signature);
4681        let write_lock_fee = Self::get_num_write_locks_in_message(message)
4682            .saturating_mul(fee_structure.lamports_per_write_lock);
4683        let compute_fee = fee_structure
4684            .compute_fee_bins
4685            .iter()
4686            .find(|bin| compute_budget.compute_unit_limit <= bin.limit)
4687            .map(|bin| bin.fee)
4688            .unwrap_or_else(|| {
4689                fee_structure
4690                    .compute_fee_bins
4691                    .last()
4692                    .map(|bin| bin.fee)
4693                    .unwrap_or_default()
4694            });
4695
4696        ((prioritization_fee
4697            .saturating_add(signature_fee)
4698            .saturating_add(write_lock_fee)
4699            .saturating_add(compute_fee) as f64)
4700            * congestion_multiplier)
4701            .round() as u64
4702    }
4703
4704    fn filter_program_errors_and_collect_fee(
4705        &self,
4706        txs: &[SanitizedTransaction],
4707        execution_results: &[TransactionExecutionResult],
4708    ) -> Vec<Result<()>> {
4709        let hash_queue = self.blockhash_queue.read().unwrap();
4710        let mut fees = 0;
4711
4712        let results = txs
4713            .iter()
4714            .zip(execution_results)
4715            .map(|(tx, execution_result)| {
4716                let (execution_status, durable_nonce_fee) = match &execution_result {
4717                    TransactionExecutionResult::Executed { details, .. } => {
4718                        Ok((&details.status, details.durable_nonce_fee.as_ref()))
4719                    }
4720                    TransactionExecutionResult::NotExecuted(err) => Err(err.clone()),
4721                }?;
4722
4723                let (lamports_per_signature, is_nonce) = durable_nonce_fee
4724                    .map(|durable_nonce_fee| durable_nonce_fee.lamports_per_signature())
4725                    .map(|maybe_lamports_per_signature| (maybe_lamports_per_signature, true))
4726                    .unwrap_or_else(|| {
4727                        (
4728                            hash_queue.get_lamports_per_signature(tx.message().recent_blockhash()),
4729                            false,
4730                        )
4731                    });
4732
4733                let lamports_per_signature =
4734                    lamports_per_signature.ok_or(TransactionError::BlockhashNotFound)?;
4735                let fee = Self::calculate_fee(
4736                    tx.message(),
4737                    lamports_per_signature,
4738                    &self.fee_structure,
4739                    self.feature_set
4740                        .is_active(&add_set_compute_unit_price_ix::id()),
4741                    self.feature_set
4742                        .is_active(&use_default_units_in_fee_calculation::id()),
4743                    self.enable_request_heap_frame_ix(),
4744                );
4745
4746                // In case of instruction error, even though no accounts
4747                // were stored we still need to charge the payer the
4748                // fee.
4749                //
4750                //...except nonce accounts, which already have their
4751                // post-load, fee deducted, pre-execute account state
4752                // stored
4753                if execution_status.is_err() && !is_nonce {
4754                    self.withdraw(tx.message().fee_payer(), fee)?;
4755                }
4756
4757                fees += fee;
4758                Ok(())
4759            })
4760            .collect();
4761
4762        self.collector_fees.fetch_add(fees, Relaxed);
4763        results
4764    }
4765
4766    /// `committed_transactions_count` is the number of transactions out of `sanitized_txs`
4767    /// that was executed. Of those, `committed_transactions_count`,
4768    /// `committed_with_failure_result_count` is the number of executed transactions that returned
4769    /// a failure result.
4770    pub fn commit_transactions(
4771        &self,
4772        sanitized_txs: &[SanitizedTransaction],
4773        loaded_txs: &mut [TransactionLoadResult],
4774        execution_results: Vec<TransactionExecutionResult>,
4775        last_blockhash: Hash,
4776        lamports_per_signature: u64,
4777        counts: CommitTransactionCounts,
4778        timings: &mut ExecuteTimings,
4779    ) -> TransactionResults {
4780        assert!(
4781            !self.freeze_started(),
4782            "commit_transactions() working on a bank that is already frozen or is undergoing freezing!"
4783        );
4784
4785        let CommitTransactionCounts {
4786            committed_transactions_count,
4787            committed_with_failure_result_count,
4788            signature_count,
4789        } = counts;
4790
4791        let tx_count = if self.bank_tranaction_count_fix_enabled() {
4792            committed_transactions_count
4793        } else {
4794            committed_transactions_count.saturating_sub(committed_with_failure_result_count)
4795        };
4796
4797        self.increment_transaction_count(tx_count);
4798        self.increment_signature_count(signature_count);
4799
4800        inc_new_counter_info!(
4801            "bank-process_transactions-txs",
4802            committed_transactions_count as usize
4803        );
4804        inc_new_counter_info!("bank-process_transactions-sigs", signature_count as usize);
4805
4806        if committed_with_failure_result_count > 0 {
4807            self.transaction_error_count
4808                .fetch_add(committed_with_failure_result_count, Relaxed);
4809        }
4810
4811        // Should be equivalent to checking `committed_transactions_count > 0`
4812        if execution_results.iter().any(|result| result.was_executed()) {
4813            self.is_delta.store(true, Relaxed);
4814            self.transaction_entries_count.fetch_add(1, Relaxed);
4815            self.transactions_per_entry_max
4816                .fetch_max(committed_transactions_count, Relaxed);
4817        }
4818
4819        let mut write_time = Measure::start("write_time");
4820        let durable_nonce = DurableNonce::from_blockhash(&last_blockhash);
4821        self.rc.accounts.store_cached(
4822            self.slot(),
4823            sanitized_txs,
4824            &execution_results,
4825            loaded_txs,
4826            &self.rent_collector,
4827            &durable_nonce,
4828            lamports_per_signature,
4829            self.preserve_rent_epoch_for_rent_exempt_accounts(),
4830        );
4831        let rent_debits = self.collect_rent(&execution_results, loaded_txs);
4832
4833        // Cached vote and stake accounts are synchronized with accounts-db
4834        // after each transaction.
4835        let mut update_stakes_cache_time = Measure::start("update_stakes_cache_time");
4836        self.update_stakes_cache(sanitized_txs, &execution_results, loaded_txs);
4837        update_stakes_cache_time.stop();
4838
4839        // once committed there is no way to unroll
4840        write_time.stop();
4841        debug!(
4842            "store: {}us txs_len={}",
4843            write_time.as_us(),
4844            sanitized_txs.len()
4845        );
4846
4847        let mut store_updated_executors_time = Measure::start("store_updated_executors_time");
4848        for execution_result in &execution_results {
4849            if let TransactionExecutionResult::Executed { details, executors } = execution_result {
4850                if details.status.is_ok() {
4851                    self.store_updated_executors(executors);
4852                }
4853            }
4854        }
4855        store_updated_executors_time.stop();
4856        saturating_add_assign!(
4857            timings.execute_accessories.update_executors_us,
4858            store_updated_executors_time.as_us()
4859        );
4860
4861        let accounts_data_len_delta = execution_results
4862            .iter()
4863            .filter_map(|execution_result| {
4864                execution_result
4865                    .details()
4866                    .map(|details| details.accounts_data_len_delta)
4867            })
4868            .sum();
4869        self.update_accounts_data_size_delta_on_chain(accounts_data_len_delta);
4870
4871        timings.saturating_add_in_place(ExecuteTimingType::StoreUs, write_time.as_us());
4872        timings.saturating_add_in_place(
4873            ExecuteTimingType::UpdateStakesCacheUs,
4874            update_stakes_cache_time.as_us(),
4875        );
4876
4877        let mut update_transaction_statuses_time = Measure::start("update_transaction_statuses");
4878        self.update_transaction_statuses(sanitized_txs, &execution_results);
4879        let fee_collection_results =
4880            self.filter_program_errors_and_collect_fee(sanitized_txs, &execution_results);
4881        update_transaction_statuses_time.stop();
4882        timings.saturating_add_in_place(
4883            ExecuteTimingType::UpdateTransactionStatuses,
4884            update_transaction_statuses_time.as_us(),
4885        );
4886
4887        TransactionResults {
4888            fee_collection_results,
4889            execution_results,
4890            rent_debits,
4891        }
4892    }
4893
4894    // Distribute collected rent fees for this slot to staked validators (excluding stakers)
4895    // according to stake.
4896    //
4897    // The nature of rent fee is the cost of doing business, every validator has to hold (or have
4898    // access to) the same list of accounts, so we pay according to stake, which is a rough proxy for
4899    // value to the network.
4900    //
4901    // Currently, rent distribution doesn't consider given validator's uptime at all (this might
4902    // change). That's because rent should be rewarded for the storage resource utilization cost.
4903    // It's treated differently from transaction fees, which is for the computing resource
4904    // utilization cost.
4905    //
4906    // We can't use collector_id (which is rotated according to stake-weighted leader schedule)
4907    // as an approximation to the ideal rent distribution to simplify and avoid this per-slot
4908    // computation for the distribution (time: N log N, space: N acct. stores; N = # of
4909    // validators).
4910    // The reason is that rent fee doesn't need to be incentivized for throughput unlike transaction
4911    // fees
4912    //
4913    // Ref: collect_fees
4914    #[allow(clippy::needless_collect)]
4915    fn distribute_rent_to_validators(
4916        &self,
4917        vote_accounts: &VoteAccountsHashMap,
4918        rent_to_be_distributed: u64,
4919    ) {
4920        let mut total_staked = 0;
4921
4922        // Collect the stake associated with each validator.
4923        // Note that a validator may be present in this vector multiple times if it happens to have
4924        // more than one staked vote account somehow
4925        let mut validator_stakes = vote_accounts
4926            .iter()
4927            .filter_map(|(_vote_pubkey, (staked, account))| {
4928                if *staked == 0 {
4929                    None
4930                } else {
4931                    total_staked += *staked;
4932                    Some((account.node_pubkey()?, *staked))
4933                }
4934            })
4935            .collect::<Vec<(Pubkey, u64)>>();
4936
4937        #[cfg(test)]
4938        if validator_stakes.is_empty() {
4939            // some tests bank.freezes() with bad staking state
4940            self.capitalization
4941                .fetch_sub(rent_to_be_distributed, Relaxed);
4942            return;
4943        }
4944        #[cfg(not(test))]
4945        assert!(!validator_stakes.is_empty());
4946
4947        // Sort first by stake and then by validator identity pubkey for determinism
4948        validator_stakes.sort_by(|(pubkey1, staked1), (pubkey2, staked2)| {
4949            match staked2.cmp(staked1) {
4950                std::cmp::Ordering::Equal => pubkey2.cmp(pubkey1),
4951                other => other,
4952            }
4953        });
4954
4955        let enforce_fix = self.no_overflow_rent_distribution_enabled();
4956
4957        let mut rent_distributed_in_initial_round = 0;
4958        let validator_rent_shares = validator_stakes
4959            .into_iter()
4960            .map(|(pubkey, staked)| {
4961                let rent_share = if !enforce_fix {
4962                    (((staked * rent_to_be_distributed) as f64) / (total_staked as f64)) as u64
4963                } else {
4964                    (((staked as u128) * (rent_to_be_distributed as u128)) / (total_staked as u128))
4965                        .try_into()
4966                        .unwrap()
4967                };
4968                rent_distributed_in_initial_round += rent_share;
4969                (pubkey, rent_share)
4970            })
4971            .collect::<Vec<(Pubkey, u64)>>();
4972
4973        // Leftover lamports after fraction calculation, will be paid to validators starting from highest stake
4974        // holder
4975        let mut leftover_lamports = rent_to_be_distributed - rent_distributed_in_initial_round;
4976
4977        let mut rewards = vec![];
4978        validator_rent_shares
4979            .into_iter()
4980            .for_each(|(pubkey, rent_share)| {
4981                let rent_to_be_paid = if leftover_lamports > 0 {
4982                    leftover_lamports -= 1;
4983                    rent_share + 1
4984                } else {
4985                    rent_share
4986                };
4987                if !enforce_fix || rent_to_be_paid > 0 {
4988                    let mut account = self
4989                        .get_account_with_fixed_root(&pubkey)
4990                        .unwrap_or_default();
4991                    if account.checked_add_lamports(rent_to_be_paid).is_err() {
4992                        // overflow adding lamports
4993                        self.capitalization.fetch_sub(rent_to_be_paid, Relaxed);
4994                        error!(
4995                            "Burned {} rent lamports instead of sending to {}",
4996                            rent_to_be_paid, pubkey
4997                        );
4998                        inc_new_counter_error!(
4999                            "bank-burned_rent_lamports",
5000                            rent_to_be_paid as usize
5001                        );
5002                    } else {
5003                        self.store_account(&pubkey, &account);
5004                        rewards.push((
5005                            pubkey,
5006                            RewardInfo {
5007                                reward_type: RewardType::Rent,
5008                                lamports: rent_to_be_paid as i64,
5009                                post_balance: account.lamports(),
5010                                commission: None,
5011                            },
5012                        ));
5013                    }
5014                }
5015            });
5016        self.rewards.write().unwrap().append(&mut rewards);
5017
5018        if enforce_fix {
5019            assert_eq!(leftover_lamports, 0);
5020        } else if leftover_lamports != 0 {
5021            warn!(
5022                "There was leftover from rent distribution: {}",
5023                leftover_lamports
5024            );
5025            self.capitalization.fetch_sub(leftover_lamports, Relaxed);
5026        }
5027    }
5028
5029    fn distribute_rent(&self) {
5030        let total_rent_collected = self.collected_rent.load(Relaxed);
5031
5032        let (burned_portion, rent_to_be_distributed) = self
5033            .rent_collector
5034            .rent
5035            .calculate_burn(total_rent_collected);
5036
5037        debug!(
5038            "distributed rent: {} (rounded from: {}, burned: {})",
5039            rent_to_be_distributed, total_rent_collected, burned_portion
5040        );
5041        self.capitalization.fetch_sub(burned_portion, Relaxed);
5042
5043        if rent_to_be_distributed == 0 {
5044            return;
5045        }
5046
5047        self.distribute_rent_to_validators(&self.vote_accounts(), rent_to_be_distributed);
5048    }
5049
5050    fn collect_rent(
5051        &self,
5052        execution_results: &[TransactionExecutionResult],
5053        loaded_txs: &mut [TransactionLoadResult],
5054    ) -> Vec<RentDebits> {
5055        let mut collected_rent: u64 = 0;
5056        let rent_debits: Vec<_> = loaded_txs
5057            .iter_mut()
5058            .zip(execution_results)
5059            .map(|((load_result, _nonce), execution_result)| {
5060                if let (Ok(loaded_transaction), true) =
5061                    (load_result, execution_result.was_executed_successfully())
5062                {
5063                    collected_rent += loaded_transaction.rent;
5064                    mem::take(&mut loaded_transaction.rent_debits)
5065                } else {
5066                    RentDebits::default()
5067                }
5068            })
5069            .collect();
5070        self.collected_rent.fetch_add(collected_rent, Relaxed);
5071        rent_debits
5072    }
5073
5074    fn run_incinerator(&self) {
5075        if let Some((account, _)) =
5076            self.get_account_modified_since_parent_with_fixed_root(&incinerator::id())
5077        {
5078            self.capitalization.fetch_sub(account.lamports(), Relaxed);
5079            self.store_account(&incinerator::id(), &AccountSharedData::default());
5080        }
5081    }
5082
5083    /// after deserialize, populate rewrites with accounts that would normally have had their data rewritten in this slot due to rent collection (but didn't)
5084    pub fn prepare_rewrites_for_hash(&self) {
5085        self.collect_rent_eagerly(true);
5086    }
5087
5088    /// Get stake and stake node accounts
5089    pub(crate) fn get_stake_accounts(&self, minimized_account_set: &DashSet<Pubkey>) {
5090        self.stakes_cache
5091            .stakes()
5092            .stake_delegations()
5093            .iter()
5094            .for_each(|(pubkey, _)| {
5095                minimized_account_set.insert(*pubkey);
5096            });
5097
5098        self.stakes_cache
5099            .stakes()
5100            .staked_nodes()
5101            .par_iter()
5102            .for_each(|(pubkey, _)| {
5103                minimized_account_set.insert(*pubkey);
5104            });
5105    }
5106
5107    /// return all end partition indexes for the given partition
5108    /// partition could be (0, 1, N). In this case we only return [1]
5109    ///  the single 'end_index' that covers this partition.
5110    /// partition could be (0, 2, N). In this case, we return [1, 2], which are all
5111    /// the 'end_index' values contained in that range.
5112    /// (0, 0, N) returns [0] as a special case.
5113    /// There is a relationship between
5114    /// 1. 'pubkey_range_from_partition'
5115    /// 2. 'partition_from_pubkey'
5116    /// 3. this function
5117    fn get_partition_end_indexes(partition: &Partition) -> Vec<PartitionIndex> {
5118        if partition.0 == partition.1 && partition.0 == 0 {
5119            // special case for start=end=0. ie. (0, 0, N). This returns [0]
5120            vec![0]
5121        } else {
5122            // normal case of (start, end, N)
5123            // so, we want [start+1, start+2, ..=end]
5124            // if start == end, then return []
5125            (partition.0..partition.1).map(|index| index + 1).collect()
5126        }
5127    }
5128
5129    fn collect_rent_eagerly(&self, just_rewrites: bool) {
5130        if self.lazy_rent_collection.load(Relaxed) {
5131            return;
5132        }
5133
5134        let mut measure = Measure::start("collect_rent_eagerly-ms");
5135        let partitions = self.rent_collection_partitions();
5136        let count = partitions.len();
5137        let rent_metrics = RentMetrics::default();
5138        // partitions will usually be 1, but could be more if we skip slots
5139        let mut parallel = count > 1;
5140        if parallel {
5141            let ranges = partitions
5142                .iter()
5143                .map(|partition| (*partition, Self::pubkey_range_from_partition(*partition)))
5144                .collect::<Vec<_>>();
5145            // test every range to make sure ranges are not overlapping
5146            // some tests collect rent from overlapping ranges
5147            // example: [(0, 31, 32), (0, 0, 128), (0, 27, 128)]
5148            // read-modify-write of an account for rent collection cannot be done in parallel
5149            'outer: for i in 0..ranges.len() {
5150                for j in 0..ranges.len() {
5151                    if i == j {
5152                        continue;
5153                    }
5154
5155                    let i = &ranges[i].1;
5156                    let j = &ranges[j].1;
5157                    // make sure i doesn't contain j
5158                    if i.contains(j.start()) || i.contains(j.end()) {
5159                        parallel = false;
5160                        break 'outer;
5161                    }
5162                }
5163            }
5164
5165            if parallel {
5166                let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
5167                thread_pool.install(|| {
5168                    ranges.into_par_iter().for_each(|range| {
5169                        self.collect_rent_in_range(range.0, range.1, just_rewrites, &rent_metrics)
5170                    });
5171                });
5172            }
5173        }
5174        if !parallel {
5175            // collect serially
5176            partitions.into_iter().for_each(|partition| {
5177                self.collect_rent_in_partition(partition, just_rewrites, &rent_metrics)
5178            });
5179        }
5180        measure.stop();
5181        datapoint_info!(
5182            "collect_rent_eagerly",
5183            ("accounts", rent_metrics.count.load(Relaxed), i64),
5184            ("partitions", count, i64),
5185            (
5186                "skipped_rewrites",
5187                self.rewrites_skipped_this_slot.read().unwrap().len(),
5188                i64
5189            ),
5190            ("total_time_us", measure.as_us(), i64),
5191            (
5192                "hold_range_us",
5193                rent_metrics.hold_range_us.load(Relaxed),
5194                i64
5195            ),
5196            ("load_us", rent_metrics.load_us.load(Relaxed), i64),
5197            ("collect_us", rent_metrics.collect_us.load(Relaxed), i64),
5198            ("hash_us", rent_metrics.hash_us.load(Relaxed), i64),
5199            ("store_us", rent_metrics.store_us.load(Relaxed), i64),
5200        );
5201    }
5202
5203    #[cfg(test)]
5204    fn restore_old_behavior_for_fragile_tests(&self) {
5205        self.lazy_rent_collection.store(true, Relaxed);
5206    }
5207
5208    fn rent_collection_partitions(&self) -> Vec<Partition> {
5209        if !self.use_fixed_collection_cycle() {
5210            // This mode is for production/development/testing.
5211            // In this mode, we iterate over the whole pubkey value range for each epochs
5212            // including warm-up epochs.
5213            // The only exception is the situation where normal epochs are relatively short
5214            // (currently less than 2 day). In that case, we arrange a single collection
5215            // cycle to be multiple of epochs so that a cycle could be greater than the 2 day.
5216            self.variable_cycle_partitions()
5217        } else {
5218            // This mode is mainly for benchmarking only.
5219            // In this mode, we always iterate over the whole pubkey value range with
5220            // <slot_count_in_two_day> slots as a collection cycle, regardless warm-up or
5221            // alignment between collection cycles and epochs.
5222            // Thus, we can simulate stable processing load of eager rent collection,
5223            // strictly proportional to the number of pubkeys since genesis.
5224            self.fixed_cycle_partitions()
5225        }
5226    }
5227
5228    /// Collect rent from `accounts`
5229    ///
5230    /// This fn is called inside a parallel loop from `collect_rent_in_partition()`.  Avoid adding
5231    /// any code that causes contention on shared memory/data (i.e. do not update atomic metrics).
5232    ///
5233    /// The return value is a struct of computed values that `collect_rent_in_partition()` will
5234    /// reduce at the end of its parallel loop.  If possible, place data/computation that cause
5235    /// contention/take locks in the return struct and process them in
5236    /// `collect_rent_from_partition()` after reducing the parallel loop.
5237    fn collect_rent_from_accounts(
5238        &self,
5239        mut accounts: Vec<(Pubkey, AccountSharedData, Slot)>,
5240        just_rewrites: bool,
5241        rent_paying_pubkeys: Option<&HashSet<Pubkey>>,
5242        partition_index: PartitionIndex,
5243    ) -> CollectRentFromAccountsInfo {
5244        let mut rent_debits = RentDebits::default();
5245        let mut total_rent_collected_info = CollectedInfo::default();
5246        let bank_slot = self.slot();
5247        let mut rewrites_skipped = Vec::with_capacity(accounts.len());
5248        let mut accounts_to_store =
5249            Vec::<(&Pubkey, &AccountSharedData)>::with_capacity(accounts.len());
5250        let mut time_collecting_rent_us = 0;
5251        let mut time_hashing_skipped_rewrites_us = 0;
5252        let mut time_storing_accounts_us = 0;
5253        let can_skip_rewrites = self.rc.accounts.accounts_db.skip_rewrites || just_rewrites;
5254        let preserve_rent_epoch_for_rent_exempt_accounts =
5255            self.preserve_rent_epoch_for_rent_exempt_accounts();
5256        for (pubkey, account, loaded_slot) in accounts.iter_mut() {
5257            let old_rent_epoch = account.rent_epoch();
5258            let (rent_collected_info, measure) =
5259                measure!(self.rent_collector.collect_from_existing_account(
5260                    pubkey,
5261                    account,
5262                    self.rc.accounts.accounts_db.filler_account_suffix.as_ref(),
5263                    preserve_rent_epoch_for_rent_exempt_accounts,
5264                ));
5265            time_collecting_rent_us += measure.as_us();
5266
5267            // only store accounts where we collected rent
5268            // but get the hash for all these accounts even if collected rent is 0 (= not updated).
5269            // Also, there's another subtle side-effect from this: this
5270            // ensures we verify the whole on-chain state (= all accounts)
5271            // via the bank delta hash slowly once per an epoch.
5272            if can_skip_rewrites
5273                && Self::skip_rewrite(
5274                    bank_slot,
5275                    rent_collected_info.rent_amount,
5276                    *loaded_slot,
5277                    old_rent_epoch,
5278                    account,
5279                )
5280            {
5281                // this would have been rewritten previously. Now we skip it.
5282                // calculate the hash that we would have gotten if we did the rewrite.
5283                // This will be needed to calculate the bank's hash.
5284                let (hash, measure) = measure!(crate::accounts_db::AccountsDb::hash_account(
5285                    self.slot(),
5286                    account,
5287                    pubkey
5288                ));
5289                time_hashing_skipped_rewrites_us += measure.as_us();
5290                rewrites_skipped.push((*pubkey, hash));
5291                assert_eq!(rent_collected_info, CollectedInfo::default());
5292            } else if !just_rewrites {
5293                if rent_collected_info.rent_amount > 0 {
5294                    if let Some(rent_paying_pubkeys) = rent_paying_pubkeys {
5295                        if !rent_paying_pubkeys.contains(pubkey) {
5296                            // inc counter instead of assert while we verify this is correct
5297                            inc_new_counter_info!("unexpected-rent-paying-pubkey", 1);
5298                            warn!(
5299                                "Collecting rent from unexpected pubkey: {}, slot: {}, parent_slot: {:?}, partition_index: {}, partition_from_pubkey: {}",
5300                                pubkey,
5301                                self.slot(),
5302                                self.parent().map(|bank| bank.slot()),
5303                                partition_index,
5304                                Bank::partition_from_pubkey(pubkey, self.epoch_schedule.slots_per_epoch),
5305                            );
5306                        }
5307                    }
5308                }
5309                total_rent_collected_info += rent_collected_info;
5310                accounts_to_store.push((pubkey, account));
5311            }
5312            rent_debits.insert(pubkey, rent_collected_info.rent_amount, account.lamports());
5313        }
5314
5315        if !accounts_to_store.is_empty() {
5316            // TODO: Maybe do not call `store_accounts()` here.  Instead return `accounts_to_store`
5317            // and have `collect_rent_in_partition()` perform all the stores.
5318            let (_, measure) = measure!(self.store_accounts((self.slot(), &accounts_to_store[..])));
5319            time_storing_accounts_us += measure.as_us();
5320        }
5321
5322        CollectRentFromAccountsInfo {
5323            rent_collected_info: total_rent_collected_info,
5324            rent_rewards: rent_debits.into_unordered_rewards_iter().collect(),
5325            rewrites_skipped,
5326            time_collecting_rent_us,
5327            time_hashing_skipped_rewrites_us,
5328            time_storing_accounts_us,
5329            num_accounts: accounts.len(),
5330        }
5331    }
5332
5333    /// convert 'partition' to a pubkey range and 'collect_rent_in_range'
5334    fn collect_rent_in_partition(
5335        &self,
5336        partition: Partition,
5337        just_rewrites: bool,
5338        metrics: &RentMetrics,
5339    ) {
5340        let subrange_full = Self::pubkey_range_from_partition(partition);
5341        self.collect_rent_in_range(partition, subrange_full, just_rewrites, metrics)
5342    }
5343
5344    /// get all pubkeys that we expect to be rent-paying or None, if this was not initialized at load time (that should only exist in test cases)
5345    fn get_rent_paying_pubkeys(&self, partition: &Partition) -> Option<HashSet<Pubkey>> {
5346        self.rc
5347            .accounts
5348            .accounts_db
5349            .accounts_index
5350            .rent_paying_accounts_by_partition
5351            .get()
5352            .and_then(|rent_paying_accounts| {
5353                rent_paying_accounts.is_initialized().then(|| {
5354                    Self::get_partition_end_indexes(partition)
5355                        .into_iter()
5356                        .flat_map(|end_index| {
5357                            rent_paying_accounts.get_pubkeys_in_partition_index(end_index)
5358                        })
5359                        .cloned()
5360                        .collect::<HashSet<_>>()
5361                })
5362            })
5363    }
5364
5365    /// load accounts with pubkeys in 'subrange_full'
5366    /// collect rent and update 'account.rent_epoch' as necessary
5367    /// store accounts, whether rent was collected or not (depending on whether we skipping rewrites is enabled)
5368    /// update bank's rewrites set for all rewrites that were skipped
5369    /// if 'just_rewrites', function will only update bank's rewrites set and not actually store any accounts.
5370    ///  This flag is used when restoring from a snapshot to calculate and verify the initial bank's delta hash.
5371    fn collect_rent_in_range(
5372        &self,
5373        partition: Partition,
5374        subrange_full: RangeInclusive<Pubkey>,
5375        just_rewrites: bool,
5376        metrics: &RentMetrics,
5377    ) {
5378        let mut hold_range = Measure::start("hold_range");
5379        let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
5380        thread_pool.install(|| {
5381            self.rc
5382                .accounts
5383                .hold_range_in_memory(&subrange_full, true, thread_pool);
5384            hold_range.stop();
5385            metrics.hold_range_us.fetch_add(hold_range.as_us(), Relaxed);
5386
5387            let rent_paying_pubkeys_ = self.get_rent_paying_pubkeys(&partition);
5388            let rent_paying_pubkeys = rent_paying_pubkeys_.as_ref();
5389
5390            // divide the range into num_threads smaller ranges and process in parallel
5391            // Note that 'pubkey_range_from_partition' cannot easily be re-used here to break the range smaller.
5392            // It has special handling of 0..0 and partition_count changes affect all ranges unevenly.
5393            let num_threads = crate::accounts_db::quarter_thread_count() as u64;
5394            let sz = std::mem::size_of::<u64>();
5395            let start_prefix = Self::prefix_from_pubkey(subrange_full.start());
5396            let end_prefix_inclusive = Self::prefix_from_pubkey(subrange_full.end());
5397            let range = end_prefix_inclusive - start_prefix;
5398            let increment = range / num_threads;
5399            let mut results = (0..num_threads)
5400                .into_par_iter()
5401                .map(|chunk| {
5402                    let offset = |chunk| start_prefix + chunk * increment;
5403                    let start = offset(chunk);
5404                    let last = chunk == num_threads - 1;
5405                    let merge_prefix = |prefix: u64, mut bound: Pubkey| {
5406                        bound.as_mut()[0..sz].copy_from_slice(&prefix.to_be_bytes());
5407                        bound
5408                    };
5409                    let start = merge_prefix(start, *subrange_full.start());
5410                    let (accounts, measure_load_accounts) = measure!(if last {
5411                        let end = *subrange_full.end();
5412                        let subrange = start..=end; // IN-clusive
5413                        self.rc
5414                            .accounts
5415                            .load_to_collect_rent_eagerly(&self.ancestors, subrange)
5416                    } else {
5417                        let end = merge_prefix(offset(chunk + 1), *subrange_full.start());
5418                        let subrange = start..end; // EX-clusive, the next 'start' will be this same value
5419                        self.rc
5420                            .accounts
5421                            .load_to_collect_rent_eagerly(&self.ancestors, subrange)
5422                    });
5423                    CollectRentInPartitionInfo::new(
5424                        self.collect_rent_from_accounts(
5425                            accounts,
5426                            just_rewrites,
5427                            rent_paying_pubkeys,
5428                            partition.1,
5429                        ),
5430                        Duration::from_nanos(measure_load_accounts.as_ns()),
5431                    )
5432                })
5433                .reduce(
5434                    CollectRentInPartitionInfo::default,
5435                    CollectRentInPartitionInfo::reduce,
5436                );
5437
5438            // We cannot assert here that we collected from all expected keys.
5439            // Some accounts may have been topped off or may have had all funds removed and gone to 0 lamports.
5440
5441            self.rc
5442                .accounts
5443                .hold_range_in_memory(&subrange_full, false, thread_pool);
5444
5445            self.collected_rent
5446                .fetch_add(results.rent_collected, Relaxed);
5447            self.update_accounts_data_size_delta_off_chain(
5448                -(results.accounts_data_size_reclaimed as i64),
5449            );
5450            self.rewards
5451                .write()
5452                .unwrap()
5453                .append(&mut results.rent_rewards);
5454            self.remember_skipped_rewrites(results.rewrites_skipped);
5455
5456            metrics
5457                .load_us
5458                .fetch_add(results.time_loading_accounts_us, Relaxed);
5459            metrics
5460                .collect_us
5461                .fetch_add(results.time_collecting_rent_us, Relaxed);
5462            metrics
5463                .hash_us
5464                .fetch_add(results.time_hashing_skipped_rewrites_us, Relaxed);
5465            metrics
5466                .store_us
5467                .fetch_add(results.time_storing_accounts_us, Relaxed);
5468            metrics.count.fetch_add(results.num_accounts, Relaxed);
5469        });
5470    }
5471
5472    // put 'rewrites_skipped' into 'self.rewrites_skipped_this_slot'
5473    fn remember_skipped_rewrites(&self, rewrites_skipped: Vec<(Pubkey, Hash)>) {
5474        if !rewrites_skipped.is_empty() {
5475            let mut rewrites_skipped_this_slot = self.rewrites_skipped_this_slot.write().unwrap();
5476            rewrites_skipped.into_iter().for_each(|(pubkey, hash)| {
5477                rewrites_skipped_this_slot.insert(pubkey, hash);
5478            });
5479        }
5480    }
5481
5482    /// return true iff storing this account is just a rewrite and can be skipped
5483    fn skip_rewrite(
5484        bank_slot: Slot,
5485        rent_amount: u64,
5486        loaded_slot: Slot,
5487        old_rent_epoch: Epoch,
5488        account: &AccountSharedData,
5489    ) -> bool {
5490        if rent_amount != 0 || account.rent_epoch() == 0 {
5491            // rent was != 0
5492            // or special case for default rent value
5493            // these cannot be skipped and must be written
5494            return false;
5495        }
5496        if old_rent_epoch != account.rent_epoch() && loaded_slot == bank_slot {
5497            // account's rent_epoch should increment even though we're not collecting rent.
5498            // and we already wrote this account in this slot, but we did not adjust rent_epoch (sys vars for example)
5499            // so, force ourselves to rewrite account if account was already written in this slot
5500            // Now, the account that was written IN this slot, where normally we would have collected rent, has the corrent 'rent_epoch'.
5501            // Only this last store will remain in the append vec.
5502            // Otherwise, later code would assume the account was written successfully in this slot with the correct 'rent_epoch'.
5503            return false;
5504        }
5505
5506        // rent was 0 and no reason to rewrite, so THIS is a rewrite we can skip
5507        true
5508    }
5509
5510    fn prefix_from_pubkey(pubkey: &Pubkey) -> u64 {
5511        const PREFIX_SIZE: usize = mem::size_of::<u64>();
5512        u64::from_be_bytes(pubkey.as_ref()[0..PREFIX_SIZE].try_into().unwrap())
5513    }
5514
5515    /// This is the inverse of pubkey_range_from_partition.
5516    /// return the lowest end_index which would contain this pubkey
5517    pub fn partition_from_pubkey(
5518        pubkey: &Pubkey,
5519        partition_count: PartitionsPerCycle,
5520    ) -> PartitionIndex {
5521        type Prefix = u64;
5522        const PREFIX_MAX: Prefix = Prefix::max_value();
5523
5524        if partition_count == 1 {
5525            return 0;
5526        }
5527
5528        // not-overflowing way of `(Prefix::max_value() + 1) / partition_count`
5529        let partition_width = (PREFIX_MAX - partition_count + 1) / partition_count + 1;
5530
5531        let prefix = Self::prefix_from_pubkey(pubkey);
5532        if prefix == 0 {
5533            return 0;
5534        }
5535
5536        if prefix == PREFIX_MAX {
5537            return partition_count - 1;
5538        }
5539
5540        let mut result = (prefix + 1) / partition_width;
5541        if (prefix + 1) % partition_width == 0 {
5542            // adjust for integer divide
5543            result = result.saturating_sub(1);
5544        }
5545        result
5546    }
5547
5548    // Mostly, the pair (start_index & end_index) is equivalent to this range:
5549    // start_index..=end_index. But it has some exceptional cases, including
5550    // this important and valid one:
5551    //   0..=0: the first partition in the new epoch when crossing epochs
5552    pub fn pubkey_range_from_partition(
5553        (start_index, end_index, partition_count): Partition,
5554    ) -> RangeInclusive<Pubkey> {
5555        assert!(start_index <= end_index);
5556        assert!(start_index < partition_count);
5557        assert!(end_index < partition_count);
5558        assert!(0 < partition_count);
5559
5560        type Prefix = u64;
5561        const PREFIX_SIZE: usize = mem::size_of::<Prefix>();
5562        const PREFIX_MAX: Prefix = Prefix::max_value();
5563
5564        let mut start_pubkey = [0x00u8; 32];
5565        let mut end_pubkey = [0xffu8; 32];
5566
5567        if partition_count == 1 {
5568            assert_eq!(start_index, 0);
5569            assert_eq!(end_index, 0);
5570            return Pubkey::new_from_array(start_pubkey)..=Pubkey::new_from_array(end_pubkey);
5571        }
5572
5573        // not-overflowing way of `(Prefix::max_value() + 1) / partition_count`
5574        let partition_width = (PREFIX_MAX - partition_count + 1) / partition_count + 1;
5575        let mut start_key_prefix = if start_index == 0 && end_index == 0 {
5576            0
5577        } else if start_index + 1 == partition_count {
5578            PREFIX_MAX
5579        } else {
5580            (start_index + 1) * partition_width
5581        };
5582
5583        let mut end_key_prefix = if end_index + 1 == partition_count {
5584            PREFIX_MAX
5585        } else {
5586            (end_index + 1) * partition_width - 1
5587        };
5588
5589        if start_index != 0 && start_index == end_index {
5590            // n..=n (n != 0): a noop pair across epochs without a gap under
5591            // multi_epoch_cycle, just nullify it.
5592            if end_key_prefix == PREFIX_MAX {
5593                start_key_prefix = end_key_prefix;
5594                start_pubkey = end_pubkey;
5595            } else {
5596                end_key_prefix = start_key_prefix;
5597                end_pubkey = start_pubkey;
5598            }
5599        }
5600
5601        start_pubkey[0..PREFIX_SIZE].copy_from_slice(&start_key_prefix.to_be_bytes());
5602        end_pubkey[0..PREFIX_SIZE].copy_from_slice(&end_key_prefix.to_be_bytes());
5603        let start_pubkey_final = Pubkey::new_from_array(start_pubkey);
5604        let end_pubkey_final = Pubkey::new_from_array(end_pubkey);
5605        trace!(
5606            "pubkey_range_from_partition: ({}-{})/{} [{}]: {}-{}",
5607            start_index,
5608            end_index,
5609            partition_count,
5610            (end_key_prefix - start_key_prefix),
5611            start_pubkey.iter().map(|x| format!("{:02x}", x)).join(""),
5612            end_pubkey.iter().map(|x| format!("{:02x}", x)).join(""),
5613        );
5614        #[cfg(test)]
5615        if start_index != end_index {
5616            assert_eq!(
5617                if start_index == 0 && end_index == 0 {
5618                    0
5619                } else {
5620                    start_index + 1
5621                },
5622                Self::partition_from_pubkey(&start_pubkey_final, partition_count),
5623                "{}, {}, start_key_prefix: {}, {}, {}",
5624                start_index,
5625                end_index,
5626                start_key_prefix,
5627                start_pubkey_final,
5628                partition_count
5629            );
5630            assert_eq!(
5631                end_index,
5632                Self::partition_from_pubkey(&end_pubkey_final, partition_count),
5633                "{}, {}, {}, {}",
5634                start_index,
5635                end_index,
5636                end_pubkey_final,
5637                partition_count
5638            );
5639            if start_index != 0 {
5640                start_pubkey[0..PREFIX_SIZE]
5641                    .copy_from_slice(&start_key_prefix.saturating_sub(1).to_be_bytes());
5642                let pubkey_test = Pubkey::new_from_array(start_pubkey);
5643                assert_eq!(
5644                    start_index,
5645                    Self::partition_from_pubkey(&pubkey_test, partition_count),
5646                    "{}, {}, start_key_prefix-1: {}, {}, {}",
5647                    start_index,
5648                    end_index,
5649                    start_key_prefix.saturating_sub(1),
5650                    pubkey_test,
5651                    partition_count
5652                );
5653            }
5654            if end_index != partition_count - 1 && end_index != 0 {
5655                end_pubkey[0..PREFIX_SIZE]
5656                    .copy_from_slice(&end_key_prefix.saturating_add(1).to_be_bytes());
5657                let pubkey_test = Pubkey::new_from_array(end_pubkey);
5658                assert_eq!(
5659                    end_index.saturating_add(1),
5660                    Self::partition_from_pubkey(&pubkey_test, partition_count),
5661                    "start: {}, end: {}, pubkey: {}, partition_count: {}, prefix_before_addition: {}, prefix after: {}",
5662                    start_index,
5663                    end_index,
5664                    pubkey_test,
5665                    partition_count,
5666                    end_key_prefix,
5667                    end_key_prefix.saturating_add(1),
5668                );
5669            }
5670        }
5671        // should be an inclusive range (a closed interval) like this:
5672        // [0xgg00-0xhhff], [0xii00-0xjjff], ... (where 0xii00 == 0xhhff + 1)
5673        start_pubkey_final..=end_pubkey_final
5674    }
5675
5676    pub fn get_partitions(
5677        slot: Slot,
5678        parent_slot: Slot,
5679        slot_count_in_two_day: SlotCount,
5680    ) -> Vec<Partition> {
5681        let parent_cycle = parent_slot / slot_count_in_two_day;
5682        let current_cycle = slot / slot_count_in_two_day;
5683        let mut parent_cycle_index = parent_slot % slot_count_in_two_day;
5684        let current_cycle_index = slot % slot_count_in_two_day;
5685        let mut partitions = vec![];
5686        if parent_cycle < current_cycle {
5687            if current_cycle_index > 0 {
5688                // generate and push gapped partitions because some slots are skipped
5689                let parent_last_cycle_index = slot_count_in_two_day - 1;
5690
5691                // ... for parent cycle
5692                partitions.push((
5693                    parent_cycle_index,
5694                    parent_last_cycle_index,
5695                    slot_count_in_two_day,
5696                ));
5697
5698                // ... for current cycle
5699                partitions.push((0, 0, slot_count_in_two_day));
5700            }
5701            parent_cycle_index = 0;
5702        }
5703
5704        partitions.push((
5705            parent_cycle_index,
5706            current_cycle_index,
5707            slot_count_in_two_day,
5708        ));
5709
5710        partitions
5711    }
5712
5713    pub(crate) fn fixed_cycle_partitions_between_slots(
5714        &self,
5715        starting_slot: Slot,
5716        ending_slot: Slot,
5717    ) -> Vec<Partition> {
5718        let slot_count_in_two_day = self.slot_count_in_two_day();
5719        Self::get_partitions(ending_slot, starting_slot, slot_count_in_two_day)
5720    }
5721
5722    fn fixed_cycle_partitions(&self) -> Vec<Partition> {
5723        self.fixed_cycle_partitions_between_slots(self.parent_slot(), self.slot())
5724    }
5725
5726    /// used only by filler accounts in debug path
5727    /// previous means slot - 1, not parent
5728    pub fn variable_cycle_partition_from_previous_slot(
5729        epoch_schedule: &EpochSchedule,
5730        slot: Slot,
5731    ) -> Partition {
5732        // similar code to Bank::variable_cycle_partitions
5733        let (current_epoch, current_slot_index) = epoch_schedule.get_epoch_and_slot_index(slot);
5734        let (parent_epoch, mut parent_slot_index) =
5735            epoch_schedule.get_epoch_and_slot_index(slot.saturating_sub(1));
5736        let cycle_params = Self::rent_single_epoch_collection_cycle_params(
5737            current_epoch,
5738            epoch_schedule.get_slots_in_epoch(current_epoch),
5739        );
5740
5741        if parent_epoch < current_epoch {
5742            parent_slot_index = 0;
5743        }
5744
5745        let generated_for_gapped_epochs = false;
5746        Self::get_partition_from_slot_indexes(
5747            cycle_params,
5748            parent_slot_index,
5749            current_slot_index,
5750            generated_for_gapped_epochs,
5751        )
5752    }
5753
5754    pub(crate) fn variable_cycle_partitions_between_slots(
5755        &self,
5756        starting_slot: Slot,
5757        ending_slot: Slot,
5758    ) -> Vec<Partition> {
5759        let (starting_epoch, mut starting_slot_index) =
5760            self.get_epoch_and_slot_index(starting_slot);
5761        let (ending_epoch, ending_slot_index) = self.get_epoch_and_slot_index(ending_slot);
5762
5763        let mut partitions = vec![];
5764        if starting_epoch < ending_epoch {
5765            let slot_skipped = (ending_slot - starting_slot) > 1;
5766            if slot_skipped {
5767                // Generate special partitions because there are skipped slots
5768                // exactly at the epoch transition.
5769
5770                let parent_last_slot_index = self.get_slots_in_epoch(starting_epoch) - 1;
5771
5772                // ... for parent epoch
5773                partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
5774                    starting_slot_index,
5775                    parent_last_slot_index,
5776                    starting_epoch,
5777                ));
5778
5779                if ending_slot_index > 0 {
5780                    // ... for current epoch
5781                    partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
5782                        0,
5783                        0,
5784                        ending_epoch,
5785                    ));
5786                }
5787            }
5788            starting_slot_index = 0;
5789        }
5790
5791        partitions.push(self.partition_from_normal_slot_indexes(
5792            starting_slot_index,
5793            ending_slot_index,
5794            ending_epoch,
5795        ));
5796
5797        partitions
5798    }
5799
5800    fn variable_cycle_partitions(&self) -> Vec<Partition> {
5801        self.variable_cycle_partitions_between_slots(self.parent_slot(), self.slot())
5802    }
5803
5804    fn do_partition_from_slot_indexes(
5805        &self,
5806        start_slot_index: SlotIndex,
5807        end_slot_index: SlotIndex,
5808        epoch: Epoch,
5809        generated_for_gapped_epochs: bool,
5810    ) -> Partition {
5811        let cycle_params = self.determine_collection_cycle_params(epoch);
5812        Self::get_partition_from_slot_indexes(
5813            cycle_params,
5814            start_slot_index,
5815            end_slot_index,
5816            generated_for_gapped_epochs,
5817        )
5818    }
5819
5820    fn get_partition_from_slot_indexes(
5821        cycle_params: RentCollectionCycleParams,
5822        start_slot_index: SlotIndex,
5823        end_slot_index: SlotIndex,
5824        generated_for_gapped_epochs: bool,
5825    ) -> Partition {
5826        let (_, _, in_multi_epoch_cycle, _, _, partition_count) = cycle_params;
5827
5828        // use common codepath for both very likely and very unlikely for the sake of minimized
5829        // risk of any miscalculation instead of negligibly faster computation per slot for the
5830        // likely case.
5831        let mut start_partition_index =
5832            Self::partition_index_from_slot_index(start_slot_index, cycle_params);
5833        let mut end_partition_index =
5834            Self::partition_index_from_slot_index(end_slot_index, cycle_params);
5835
5836        // Adjust partition index for some edge cases
5837        let is_special_new_epoch = start_slot_index == 0 && end_slot_index != 1;
5838        let in_middle_of_cycle = start_partition_index > 0;
5839        if in_multi_epoch_cycle && is_special_new_epoch && in_middle_of_cycle {
5840            // Adjust slot indexes so that the final partition ranges are continuous!
5841            // This is need because the caller gives us off-by-one indexes when
5842            // an epoch boundary is crossed.
5843            // Usually there is no need for this adjustment because cycles are aligned
5844            // with epochs. But for multi-epoch cycles, adjust the indexes if it
5845            // happens in the middle of a cycle for both gapped and not-gapped cases:
5846            //
5847            // epoch (slot range)|slot idx.*1|raw part. idx.|adj. part. idx.|epoch boundary
5848            // ------------------+-----------+--------------+---------------+--------------
5849            // 3 (20..30)        | [7..8]    |   7.. 8      |   7.. 8
5850            //                   | [8..9]    |   8.. 9      |   8.. 9
5851            // 4 (30..40)        | [0..0]    |<10>..10      | <9>..10      <--- not gapped
5852            //                   | [0..1]    |  10..11      |  10..12
5853            //                   | [1..2]    |  11..12      |  11..12
5854            //                   | [2..9   *2|  12..19      |  12..19      <-+
5855            // 5 (40..50)        |  0..0   *2|<20>..<20>    |<19>..<19> *3 <-+- gapped
5856            //                   |  0..4]    |<20>..24      |<19>..24      <-+
5857            //                   | [4..5]    |  24..25      |  24..25
5858            //                   | [5..6]    |  25..26      |  25..26
5859            //
5860            // NOTE: <..> means the adjusted slots
5861            //
5862            // *1: The range of parent_bank.slot() and current_bank.slot() is firstly
5863            //     split by the epoch boundaries and then the split ones are given to us.
5864            //     The original ranges are denoted as [...]
5865            // *2: These are marked with generated_for_gapped_epochs = true.
5866            // *3: This becomes no-op partition
5867            start_partition_index -= 1;
5868            if generated_for_gapped_epochs {
5869                assert_eq!(start_slot_index, end_slot_index);
5870                end_partition_index -= 1;
5871            }
5872        }
5873
5874        (start_partition_index, end_partition_index, partition_count)
5875    }
5876
5877    fn partition_from_normal_slot_indexes(
5878        &self,
5879        start_slot_index: SlotIndex,
5880        end_slot_index: SlotIndex,
5881        epoch: Epoch,
5882    ) -> Partition {
5883        self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, false)
5884    }
5885
5886    fn partition_from_slot_indexes_with_gapped_epochs(
5887        &self,
5888        start_slot_index: SlotIndex,
5889        end_slot_index: SlotIndex,
5890        epoch: Epoch,
5891    ) -> Partition {
5892        self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, true)
5893    }
5894
5895    fn rent_single_epoch_collection_cycle_params(
5896        epoch: Epoch,
5897        slot_count_per_epoch: SlotCount,
5898    ) -> RentCollectionCycleParams {
5899        (
5900            epoch,
5901            slot_count_per_epoch,
5902            false,
5903            0,
5904            1,
5905            slot_count_per_epoch,
5906        )
5907    }
5908
5909    fn determine_collection_cycle_params(&self, epoch: Epoch) -> RentCollectionCycleParams {
5910        let slot_count_per_epoch = self.get_slots_in_epoch(epoch);
5911
5912        if !self.use_multi_epoch_collection_cycle(epoch) {
5913            // mnb should always go through this code path
5914            Self::rent_single_epoch_collection_cycle_params(epoch, slot_count_per_epoch)
5915        } else {
5916            let epoch_count_in_cycle = self.slot_count_in_two_day() / slot_count_per_epoch;
5917            let partition_count = slot_count_per_epoch * epoch_count_in_cycle;
5918
5919            (
5920                epoch,
5921                slot_count_per_epoch,
5922                true,
5923                self.first_normal_epoch(),
5924                epoch_count_in_cycle,
5925                partition_count,
5926            )
5927        }
5928    }
5929
5930    fn partition_index_from_slot_index(
5931        slot_index_in_epoch: SlotIndex,
5932        (
5933            epoch,
5934            slot_count_per_epoch,
5935            _,
5936            base_epoch,
5937            epoch_count_per_cycle,
5938            _,
5939        ): RentCollectionCycleParams,
5940    ) -> PartitionIndex {
5941        let epoch_offset = epoch - base_epoch;
5942        let epoch_index_in_cycle = epoch_offset % epoch_count_per_cycle;
5943        slot_index_in_epoch + epoch_index_in_cycle * slot_count_per_epoch
5944    }
5945
5946    // Given short epochs, it's too costly to collect rent eagerly
5947    // within an epoch, so lower the frequency of it.
5948    // These logic isn't strictly eager anymore and should only be used
5949    // for development/performance purpose.
5950    // Absolutely not under ClusterType::MainnetBeta!!!!
5951    fn use_multi_epoch_collection_cycle(&self, epoch: Epoch) -> bool {
5952        // Force normal behavior, disabling multi epoch collection cycle for manual local testing
5953        #[cfg(not(test))]
5954        if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
5955        {
5956            return false;
5957        }
5958
5959        epoch >= self.first_normal_epoch()
5960            && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
5961    }
5962
5963    pub(crate) fn use_fixed_collection_cycle(&self) -> bool {
5964        // Force normal behavior, disabling fixed collection cycle for manual local testing
5965        #[cfg(not(test))]
5966        if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
5967        {
5968            return false;
5969        }
5970
5971        self.cluster_type() != ClusterType::MainnetBeta
5972            && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
5973    }
5974
5975    fn slot_count_in_two_day(&self) -> SlotCount {
5976        Self::slot_count_in_two_day_helper(self.ticks_per_slot)
5977    }
5978
5979    // This value is specially chosen to align with slots per epoch in mainnet-beta and testnet
5980    // Also, assume 500GB account data set as the extreme, then for 2 day (=48 hours) to collect
5981    // rent eagerly, we'll consume 5.7 MB/s IO bandwidth, bidirectionally.
5982    pub fn slot_count_in_two_day_helper(ticks_per_slot: SlotCount) -> SlotCount {
5983        2 * DEFAULT_TICKS_PER_SECOND * SECONDS_PER_DAY / ticks_per_slot
5984    }
5985
5986    fn slot_count_per_normal_epoch(&self) -> SlotCount {
5987        self.get_slots_in_epoch(self.first_normal_epoch())
5988    }
5989
5990    pub fn cluster_type(&self) -> ClusterType {
5991        // unwrap is safe; self.cluster_type is ensured to be Some() always...
5992        // we only using Option here for ABI compatibility...
5993        self.cluster_type.unwrap()
5994    }
5995
5996    /// Process a batch of transactions.
5997    #[must_use]
5998    pub fn load_execute_and_commit_transactions(
5999        &self,
6000        batch: &TransactionBatch,
6001        max_age: usize,
6002        collect_balances: bool,
6003        enable_cpi_recording: bool,
6004        enable_log_recording: bool,
6005        enable_return_data_recording: bool,
6006        timings: &mut ExecuteTimings,
6007        log_messages_bytes_limit: Option<usize>,
6008    ) -> (TransactionResults, TransactionBalancesSet) {
6009        let pre_balances = if collect_balances {
6010            self.collect_balances(batch)
6011        } else {
6012            vec![]
6013        };
6014
6015        let LoadAndExecuteTransactionsOutput {
6016            mut loaded_transactions,
6017            execution_results,
6018            executed_transactions_count,
6019            executed_with_successful_result_count,
6020            signature_count,
6021            ..
6022        } = self.load_and_execute_transactions(
6023            batch,
6024            max_age,
6025            enable_cpi_recording,
6026            enable_log_recording,
6027            enable_return_data_recording,
6028            timings,
6029            None,
6030            log_messages_bytes_limit,
6031        );
6032
6033        let (last_blockhash, lamports_per_signature) =
6034            self.last_blockhash_and_lamports_per_signature();
6035        let results = self.commit_transactions(
6036            batch.sanitized_transactions(),
6037            &mut loaded_transactions,
6038            execution_results,
6039            last_blockhash,
6040            lamports_per_signature,
6041            CommitTransactionCounts {
6042                committed_transactions_count: executed_transactions_count as u64,
6043                committed_with_failure_result_count: executed_transactions_count
6044                    .saturating_sub(executed_with_successful_result_count)
6045                    as u64,
6046                signature_count,
6047            },
6048            timings,
6049        );
6050        let post_balances = if collect_balances {
6051            self.collect_balances(batch)
6052        } else {
6053            vec![]
6054        };
6055        (
6056            results,
6057            TransactionBalancesSet::new(pre_balances, post_balances),
6058        )
6059    }
6060
6061    /// Process a Transaction. This is used for unit tests and simply calls the vector
6062    /// Bank::process_transactions method.
6063    pub fn process_transaction(&self, tx: &Transaction) -> Result<()> {
6064        self.try_process_transactions(std::iter::once(tx))?[0].clone()?;
6065        tx.signatures
6066            .get(0)
6067            .map_or(Ok(()), |sig| self.get_signature_status(sig).unwrap())
6068    }
6069
6070    /// Process a Transaction and store program log data. This is used for unit tests, and simply
6071    /// replicates the vector Bank::process_transactions method with `enable_cpi_recording: true`
6072    pub fn process_transaction_with_logs(&self, tx: &Transaction) -> Result<()> {
6073        let txs = vec![VersionedTransaction::from(tx.clone())];
6074        let batch = self.prepare_entry_batch(txs)?;
6075        let _results = self.load_execute_and_commit_transactions(
6076            &batch,
6077            MAX_PROCESSING_AGE,
6078            false,
6079            false,
6080            true,
6081            false,
6082            &mut ExecuteTimings::default(),
6083            None,
6084        );
6085        tx.signatures
6086            .get(0)
6087            .map_or(Ok(()), |sig| self.get_signature_status(sig).unwrap())
6088    }
6089
6090    /// Process multiple transaction in a single batch. This is used for benches and unit tests.
6091    ///
6092    /// # Panics
6093    ///
6094    /// Panics if any of the transactions do not pass sanitization checks.
6095    #[must_use]
6096    pub fn process_transactions<'a>(
6097        &self,
6098        txs: impl Iterator<Item = &'a Transaction>,
6099    ) -> Vec<Result<()>> {
6100        self.try_process_transactions(txs).unwrap()
6101    }
6102
6103    /// Process multiple transaction in a single batch. This is used for benches and unit tests.
6104    /// Short circuits if any of the transactions do not pass sanitization checks.
6105    pub fn try_process_transactions<'a>(
6106        &self,
6107        txs: impl Iterator<Item = &'a Transaction>,
6108    ) -> Result<Vec<Result<()>>> {
6109        let txs = txs
6110            .map(|tx| VersionedTransaction::from(tx.clone()))
6111            .collect();
6112        self.try_process_entry_transactions(txs)
6113    }
6114
6115    /// Process entry transactions in a single batch. This is used for benches and unit tests.
6116    ///
6117    /// # Panics
6118    ///
6119    /// Panics if any of the transactions do not pass sanitization checks.
6120    #[must_use]
6121    pub fn process_entry_transactions(&self, txs: Vec<VersionedTransaction>) -> Vec<Result<()>> {
6122        self.try_process_entry_transactions(txs).unwrap()
6123    }
6124
6125    /// Process multiple transaction in a single batch. This is used for benches and unit tests.
6126    /// Short circuits if any of the transactions do not pass sanitization checks.
6127    pub fn try_process_entry_transactions(
6128        &self,
6129        txs: Vec<VersionedTransaction>,
6130    ) -> Result<Vec<Result<()>>> {
6131        let batch = self.prepare_entry_batch(txs)?;
6132        Ok(self.process_transaction_batch(&batch))
6133    }
6134
6135    #[must_use]
6136    fn process_transaction_batch(&self, batch: &TransactionBatch) -> Vec<Result<()>> {
6137        self.load_execute_and_commit_transactions(
6138            batch,
6139            MAX_PROCESSING_AGE,
6140            false,
6141            false,
6142            false,
6143            false,
6144            &mut ExecuteTimings::default(),
6145            None,
6146        )
6147        .0
6148        .fee_collection_results
6149    }
6150
6151    /// Create, sign, and process a Transaction from `keypair` to `to` of
6152    /// `n` lamports where `blockhash` is the last Entry ID observed by the client.
6153    pub fn transfer(&self, n: u64, keypair: &Keypair, to: &Pubkey) -> Result<Signature> {
6154        let blockhash = self.last_blockhash();
6155        let tx = system_transaction::transfer(keypair, to, n, blockhash);
6156        let signature = tx.signatures[0];
6157        self.process_transaction(&tx).map(|_| signature)
6158    }
6159
6160    pub fn read_balance(account: &AccountSharedData) -> u64 {
6161        account.lamports()
6162    }
6163    /// Each program would need to be able to introspect its own state
6164    /// this is hard-coded to the Budget language
6165    pub fn get_balance(&self, pubkey: &Pubkey) -> u64 {
6166        self.get_account(pubkey)
6167            .map(|x| Self::read_balance(&x))
6168            .unwrap_or(0)
6169    }
6170
6171    /// Compute all the parents of the bank in order
6172    pub fn parents(&self) -> Vec<Arc<Bank>> {
6173        let mut parents = vec![];
6174        let mut bank = self.parent();
6175        while let Some(parent) = bank {
6176            parents.push(parent.clone());
6177            bank = parent.parent();
6178        }
6179        parents
6180    }
6181
6182    /// Compute all the parents of the bank including this bank itself
6183    pub fn parents_inclusive(self: Arc<Self>) -> Vec<Arc<Bank>> {
6184        let mut parents = self.parents();
6185        parents.insert(0, self);
6186        parents
6187    }
6188
6189    pub fn store_account<T: ReadableAccount + Sync + ZeroLamport>(
6190        &self,
6191        pubkey: &Pubkey,
6192        account: &T,
6193    ) {
6194        self.store_accounts((self.slot(), &[(pubkey, account)][..]))
6195    }
6196
6197    pub fn store_accounts<'a, T: ReadableAccount + Sync + ZeroLamport>(
6198        &self,
6199        accounts: impl StorableAccounts<'a, T>,
6200    ) {
6201        assert!(!self.freeze_started());
6202        let mut m = Measure::start("stakes_cache.check_and_store");
6203        (0..accounts.len()).into_iter().for_each(|i| {
6204            self.stakes_cache
6205                .check_and_store(accounts.pubkey(i), accounts.account(i))
6206        });
6207        self.rc.accounts.store_accounts_cached(accounts);
6208        m.stop();
6209        self.rc
6210            .accounts
6211            .accounts_db
6212            .stats
6213            .stakes_cache_check_and_store_us
6214            .fetch_add(m.as_us(), Relaxed);
6215    }
6216
6217    pub fn force_flush_accounts_cache(&self) {
6218        self.rc
6219            .accounts
6220            .accounts_db
6221            .flush_accounts_cache(true, Some(self.slot()))
6222    }
6223
6224    pub fn flush_accounts_cache_if_needed(&self) {
6225        self.rc
6226            .accounts
6227            .accounts_db
6228            .flush_accounts_cache(false, Some(self.slot()))
6229    }
6230
6231    #[cfg(test)]
6232    pub fn flush_accounts_cache_slot(&self) {
6233        self.rc
6234            .accounts
6235            .accounts_db
6236            .flush_accounts_cache_slot(self.slot())
6237    }
6238
6239    pub fn expire_old_recycle_stores(&self) {
6240        self.rc.accounts.accounts_db.expire_old_recycle_stores()
6241    }
6242
6243    /// Technically this issues (or even burns!) new lamports,
6244    /// so be extra careful for its usage
6245    fn store_account_and_update_capitalization(
6246        &self,
6247        pubkey: &Pubkey,
6248        new_account: &AccountSharedData,
6249    ) {
6250        let old_account_data_size =
6251            if let Some(old_account) = self.get_account_with_fixed_root(pubkey) {
6252                match new_account.lamports().cmp(&old_account.lamports()) {
6253                    std::cmp::Ordering::Greater => {
6254                        let increased = new_account.lamports() - old_account.lamports();
6255                        trace!(
6256                            "store_account_and_update_capitalization: increased: {} {}",
6257                            pubkey,
6258                            increased
6259                        );
6260                        self.capitalization.fetch_add(increased, Relaxed);
6261                    }
6262                    std::cmp::Ordering::Less => {
6263                        let decreased = old_account.lamports() - new_account.lamports();
6264                        trace!(
6265                            "store_account_and_update_capitalization: decreased: {} {}",
6266                            pubkey,
6267                            decreased
6268                        );
6269                        self.capitalization.fetch_sub(decreased, Relaxed);
6270                    }
6271                    std::cmp::Ordering::Equal => {}
6272                }
6273                old_account.data().len()
6274            } else {
6275                trace!(
6276                    "store_account_and_update_capitalization: created: {} {}",
6277                    pubkey,
6278                    new_account.lamports()
6279                );
6280                self.capitalization
6281                    .fetch_add(new_account.lamports(), Relaxed);
6282                0
6283            };
6284
6285        self.store_account(pubkey, new_account);
6286        self.calculate_and_update_accounts_data_size_delta_off_chain(
6287            old_account_data_size,
6288            new_account.data().len(),
6289        );
6290    }
6291
6292    fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
6293        match self.get_account_with_fixed_root(pubkey) {
6294            Some(mut account) => {
6295                let min_balance = match get_system_account_kind(&account) {
6296                    Some(SystemAccountKind::Nonce) => self
6297                        .rent_collector
6298                        .rent
6299                        .minimum_balance(nonce::State::size()),
6300                    _ => 0,
6301                };
6302
6303                lamports
6304                    .checked_add(min_balance)
6305                    .filter(|required_balance| *required_balance <= account.lamports())
6306                    .ok_or(TransactionError::InsufficientFundsForFee)?;
6307                account
6308                    .checked_sub_lamports(lamports)
6309                    .map_err(|_| TransactionError::InsufficientFundsForFee)?;
6310                self.store_account(pubkey, &account);
6311
6312                Ok(())
6313            }
6314            None => Err(TransactionError::AccountNotFound),
6315        }
6316    }
6317
6318    pub fn deposit(
6319        &self,
6320        pubkey: &Pubkey,
6321        lamports: u64,
6322    ) -> std::result::Result<u64, LamportsError> {
6323        // This doesn't collect rents intentionally.
6324        // Rents should only be applied to actual TXes
6325        let mut account = self.get_account_with_fixed_root(pubkey).unwrap_or_default();
6326        account.checked_add_lamports(lamports)?;
6327        self.store_account(pubkey, &account);
6328        Ok(account.lamports())
6329    }
6330
6331    pub fn accounts(&self) -> Arc<Accounts> {
6332        self.rc.accounts.clone()
6333    }
6334
6335    fn finish_init(
6336        &mut self,
6337        genesis_config: &GenesisConfig,
6338        additional_builtins: Option<&Builtins>,
6339        debug_do_not_add_builtins: bool,
6340    ) {
6341        self.rewards_pool_pubkeys =
6342            Arc::new(genesis_config.rewards_pools.keys().cloned().collect());
6343
6344        let mut builtins = builtins::get();
6345        if let Some(additional_builtins) = additional_builtins {
6346            builtins
6347                .genesis_builtins
6348                .extend_from_slice(&additional_builtins.genesis_builtins);
6349            builtins
6350                .feature_transitions
6351                .extend_from_slice(&additional_builtins.feature_transitions);
6352        }
6353        if !debug_do_not_add_builtins {
6354            for builtin in builtins.genesis_builtins {
6355                self.add_builtin(
6356                    &builtin.name,
6357                    &builtin.id,
6358                    builtin.process_instruction_with_context,
6359                );
6360            }
6361            for precompile in get_precompiles() {
6362                if precompile.feature.is_none() {
6363                    self.add_precompile(&precompile.program_id);
6364                }
6365            }
6366        }
6367        self.builtin_feature_transitions = Arc::new(builtins.feature_transitions);
6368
6369        self.apply_feature_activations(
6370            ApplyFeatureActivationsCaller::FinishInit,
6371            debug_do_not_add_builtins,
6372        );
6373
6374        if self
6375            .feature_set
6376            .is_active(&feature_set::cap_accounts_data_len::id())
6377        {
6378            self.cost_tracker = RwLock::new(CostTracker::new_with_account_data_size_limit(Some(
6379                self.accounts_data_size_limit()
6380                    .saturating_sub(self.accounts_data_size_initial),
6381            )));
6382        }
6383    }
6384
6385    pub fn set_inflation(&self, inflation: Inflation) {
6386        *self.inflation.write().unwrap() = inflation;
6387    }
6388
6389    pub fn set_compute_budget(&mut self, compute_budget: Option<ComputeBudget>) {
6390        self.compute_budget = compute_budget;
6391    }
6392
6393    pub fn hard_forks(&self) -> Arc<RwLock<HardForks>> {
6394        self.hard_forks.clone()
6395    }
6396
6397    // Hi! leaky abstraction here....
6398    // try to use get_account_with_fixed_root() if it's called ONLY from on-chain runtime account
6399    // processing. That alternative fn provides more safety.
6400    pub fn get_account(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
6401        self.get_account_modified_slot(pubkey)
6402            .map(|(acc, _slot)| acc)
6403    }
6404
6405    // Hi! leaky abstraction here....
6406    // use this over get_account() if it's called ONLY from on-chain runtime account
6407    // processing (i.e. from in-band replay/banking stage; that ensures root is *fixed* while
6408    // running).
6409    // pro: safer assertion can be enabled inside AccountsDb
6410    // con: panics!() if called from off-chain processing
6411    pub fn get_account_with_fixed_root(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
6412        self.load_slow_with_fixed_root(&self.ancestors, pubkey)
6413            .map(|(acc, _slot)| acc)
6414    }
6415
6416    pub fn get_account_modified_slot(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
6417        self.load_slow(&self.ancestors, pubkey)
6418    }
6419
6420    fn load_slow(
6421        &self,
6422        ancestors: &Ancestors,
6423        pubkey: &Pubkey,
6424    ) -> Option<(AccountSharedData, Slot)> {
6425        // get_account (= primary this fn caller) may be called from on-chain Bank code even if we
6426        // try hard to use get_account_with_fixed_root for that purpose...
6427        // so pass safer LoadHint:Unspecified here as a fallback
6428        self.rc.accounts.load_without_fixed_root(ancestors, pubkey)
6429    }
6430
6431    fn load_slow_with_fixed_root(
6432        &self,
6433        ancestors: &Ancestors,
6434        pubkey: &Pubkey,
6435    ) -> Option<(AccountSharedData, Slot)> {
6436        self.rc.accounts.load_with_fixed_root(ancestors, pubkey)
6437    }
6438
6439    pub fn get_program_accounts(
6440        &self,
6441        program_id: &Pubkey,
6442        config: &ScanConfig,
6443    ) -> ScanResult<Vec<TransactionAccount>> {
6444        self.rc
6445            .accounts
6446            .load_by_program(&self.ancestors, self.bank_id, program_id, config)
6447    }
6448
6449    pub fn get_filtered_program_accounts<F: Fn(&AccountSharedData) -> bool>(
6450        &self,
6451        program_id: &Pubkey,
6452        filter: F,
6453        config: &ScanConfig,
6454    ) -> ScanResult<Vec<TransactionAccount>> {
6455        self.rc.accounts.load_by_program_with_filter(
6456            &self.ancestors,
6457            self.bank_id,
6458            program_id,
6459            filter,
6460            config,
6461        )
6462    }
6463
6464    pub fn get_filtered_indexed_accounts<F: Fn(&AccountSharedData) -> bool>(
6465        &self,
6466        index_key: &IndexKey,
6467        filter: F,
6468        config: &ScanConfig,
6469        byte_limit_for_scan: Option<usize>,
6470    ) -> ScanResult<Vec<TransactionAccount>> {
6471        self.rc.accounts.load_by_index_key_with_filter(
6472            &self.ancestors,
6473            self.bank_id,
6474            index_key,
6475            filter,
6476            config,
6477            byte_limit_for_scan,
6478        )
6479    }
6480
6481    pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
6482        self.rc.accounts.account_indexes_include_key(key)
6483    }
6484
6485    pub fn get_all_accounts_with_modified_slots(&self) -> ScanResult<Vec<PubkeyAccountSlot>> {
6486        self.rc.accounts.load_all(&self.ancestors, self.bank_id)
6487    }
6488
6489    pub fn get_program_accounts_modified_since_parent(
6490        &self,
6491        program_id: &Pubkey,
6492    ) -> Vec<TransactionAccount> {
6493        self.rc
6494            .accounts
6495            .load_by_program_slot(self.slot(), Some(program_id))
6496    }
6497
6498    pub fn get_transaction_logs(
6499        &self,
6500        address: Option<&Pubkey>,
6501    ) -> Option<Vec<TransactionLogInfo>> {
6502        self.transaction_log_collector
6503            .read()
6504            .unwrap()
6505            .get_logs_for_address(address)
6506    }
6507
6508    pub fn get_all_accounts_modified_since_parent(&self) -> Vec<TransactionAccount> {
6509        self.rc.accounts.load_by_program_slot(self.slot(), None)
6510    }
6511
6512    // if you want get_account_modified_since_parent without fixed_root, please define so...
6513    fn get_account_modified_since_parent_with_fixed_root(
6514        &self,
6515        pubkey: &Pubkey,
6516    ) -> Option<(AccountSharedData, Slot)> {
6517        let just_self: Ancestors = Ancestors::from(vec![self.slot()]);
6518        if let Some((account, slot)) = self.load_slow_with_fixed_root(&just_self, pubkey) {
6519            if slot == self.slot() {
6520                return Some((account, slot));
6521            }
6522        }
6523        None
6524    }
6525
6526    pub fn get_largest_accounts(
6527        &self,
6528        num: usize,
6529        filter_by_address: &HashSet<Pubkey>,
6530        filter: AccountAddressFilter,
6531    ) -> ScanResult<Vec<(Pubkey, u64)>> {
6532        self.rc.accounts.load_largest_accounts(
6533            &self.ancestors,
6534            self.bank_id,
6535            num,
6536            filter_by_address,
6537            filter,
6538        )
6539    }
6540
6541    pub fn transaction_count(&self) -> u64 {
6542        self.transaction_count.load(Relaxed)
6543    }
6544
6545    pub fn transaction_error_count(&self) -> u64 {
6546        self.transaction_error_count.load(Relaxed)
6547    }
6548
6549    pub fn transaction_entries_count(&self) -> u64 {
6550        self.transaction_entries_count.load(Relaxed)
6551    }
6552
6553    pub fn transactions_per_entry_max(&self) -> u64 {
6554        self.transactions_per_entry_max.load(Relaxed)
6555    }
6556
6557    fn increment_transaction_count(&self, tx_count: u64) {
6558        self.transaction_count.fetch_add(tx_count, Relaxed);
6559    }
6560
6561    pub fn signature_count(&self) -> u64 {
6562        self.signature_count.load(Relaxed)
6563    }
6564
6565    fn increment_signature_count(&self, signature_count: u64) {
6566        self.signature_count.fetch_add(signature_count, Relaxed);
6567    }
6568
6569    pub fn get_signature_status_processed_since_parent(
6570        &self,
6571        signature: &Signature,
6572    ) -> Option<Result<()>> {
6573        if let Some((slot, status)) = self.get_signature_status_slot(signature) {
6574            if slot <= self.slot() {
6575                return Some(status);
6576            }
6577        }
6578        None
6579    }
6580
6581    pub fn get_signature_status_with_blockhash(
6582        &self,
6583        signature: &Signature,
6584        blockhash: &Hash,
6585    ) -> Option<Result<()>> {
6586        let rcache = self.status_cache.read().unwrap();
6587        rcache
6588            .get_status(signature, blockhash, &self.ancestors)
6589            .map(|v| v.1)
6590    }
6591
6592    pub fn get_signature_status_slot(&self, signature: &Signature) -> Option<(Slot, Result<()>)> {
6593        let rcache = self.status_cache.read().unwrap();
6594        rcache.get_status_any_blockhash(signature, &self.ancestors)
6595    }
6596
6597    pub fn get_signature_status(&self, signature: &Signature) -> Option<Result<()>> {
6598        self.get_signature_status_slot(signature).map(|v| v.1)
6599    }
6600
6601    pub fn has_signature(&self, signature: &Signature) -> bool {
6602        self.get_signature_status_slot(signature).is_some()
6603    }
6604
6605    /// Hash the `accounts` HashMap. This represents a validator's interpretation
6606    ///  of the delta of the ledger since the last vote and up to now
6607    fn hash_internal_state(&self) -> Hash {
6608        // If there are no accounts, return the hash of the previous state and the latest blockhash
6609        let accounts_delta_hash = self
6610            .rc
6611            .accounts
6612            .bank_hash_info_at(self.slot(), &self.rewrites_skipped_this_slot);
6613        let mut signature_count_buf = [0u8; 8];
6614        LittleEndian::write_u64(&mut signature_count_buf[..], self.signature_count() as u64);
6615
6616        let mut hash = hashv(&[
6617            self.parent_hash.as_ref(),
6618            accounts_delta_hash.hash.as_ref(),
6619            &signature_count_buf,
6620            self.last_blockhash().as_ref(),
6621        ]);
6622
6623        let buf = self
6624            .hard_forks
6625            .read()
6626            .unwrap()
6627            .get_hash_data(self.slot(), self.parent_slot());
6628        if let Some(buf) = buf {
6629            let hard_forked_hash = extend_and_hash(&hash, &buf);
6630            warn!(
6631                "hard fork at slot {} by hashing {:?}: {} => {}",
6632                self.slot(),
6633                buf,
6634                hash,
6635                hard_forked_hash
6636            );
6637            hash = hard_forked_hash;
6638        }
6639
6640        info!(
6641            "bank frozen: {} hash: {} accounts_delta: {} signature_count: {} last_blockhash: {} capitalization: {}",
6642            self.slot(),
6643            hash,
6644            accounts_delta_hash.hash,
6645            self.signature_count(),
6646            self.last_blockhash(),
6647            self.capitalization(),
6648        );
6649
6650        info!(
6651            "accounts hash slot: {} stats: {:?}",
6652            self.slot(),
6653            accounts_delta_hash.stats,
6654        );
6655        hash
6656    }
6657
6658    /// Recalculate the hash_internal_state from the account stores. Would be used to verify a
6659    /// snapshot.
6660    /// return true if all is good
6661    /// Only called from startup or test code.
6662    #[must_use]
6663    pub fn verify_bank_hash(&self, config: VerifyBankHash) -> bool {
6664        let accounts = &self.rc.accounts;
6665        // Wait until initial hash calc is complete before starting a new hash calc.
6666        // This should only occur when we halt at a slot in ledger-tool.
6667        accounts
6668            .accounts_db
6669            .verify_accounts_hash_in_bg
6670            .wait_for_complete();
6671
6672        if config.require_rooted_bank
6673            && !accounts
6674                .accounts_db
6675                .accounts_index
6676                .is_alive_root(self.slot())
6677        {
6678            if let Some(parent) = self.parent() {
6679                info!("{} is not a root, so attempting to verify bank hash on parent bank at slot: {}", self.slot(), parent.slot());
6680                return parent.verify_bank_hash(config);
6681            } else {
6682                // this will result in mismatch errors
6683                // accounts hash calc doesn't include unrooted slots
6684                panic!("cannot verify bank hash when bank is not a root");
6685            }
6686        }
6687        let slot = self.slot();
6688        let ancestors = &self.ancestors;
6689        let cap = self.capitalization();
6690        let epoch_schedule = self.epoch_schedule();
6691        let rent_collector = self.rent_collector();
6692        if config.run_in_background {
6693            let ancestors = ancestors.clone();
6694            let accounts = Arc::clone(accounts);
6695            let epoch_schedule = *epoch_schedule;
6696            let rent_collector = rent_collector.clone();
6697            let accounts_ = Arc::clone(&accounts);
6698            accounts.accounts_db.verify_accounts_hash_in_bg.start(|| {
6699                Builder::new()
6700                    .name("solBgHashVerify".into())
6701                    .spawn(move || {
6702                        info!(
6703                            "running initial verification accounts hash calculation in background"
6704                        );
6705                        let result = accounts_.verify_bank_hash_and_lamports(
6706                            slot,
6707                            &ancestors,
6708                            cap,
6709                            config.test_hash_calculation,
6710                            &epoch_schedule,
6711                            &rent_collector,
6712                            config.can_cached_slot_be_unflushed,
6713                            config.ignore_mismatch,
6714                            config.store_hash_raw_data_for_debug,
6715                            // true to run using bg thread pool
6716                            true,
6717                        );
6718                        accounts_
6719                            .accounts_db
6720                            .verify_accounts_hash_in_bg
6721                            .background_finished();
6722                        result
6723                    })
6724                    .unwrap()
6725            });
6726            true // initial result is true. We haven't failed yet. If verification fails, we'll panic from bg thread.
6727        } else {
6728            let result = accounts.verify_bank_hash_and_lamports(
6729                slot,
6730                &self.ancestors,
6731                cap,
6732                config.test_hash_calculation,
6733                epoch_schedule,
6734                rent_collector,
6735                config.can_cached_slot_be_unflushed,
6736                config.ignore_mismatch,
6737                config.store_hash_raw_data_for_debug,
6738                // fg is waiting for this to run, so we can use the fg thread pool
6739                false,
6740            );
6741            self.set_initial_accounts_hash_verification_completed();
6742            result
6743        }
6744    }
6745
6746    /// Specify that initial verification has completed.
6747    /// Called internally when verification runs in the foreground thread.
6748    /// Also has to be called by some tests which don't do verification on startup.
6749    pub fn set_initial_accounts_hash_verification_completed(&self) {
6750        self.rc
6751            .accounts
6752            .accounts_db
6753            .verify_accounts_hash_in_bg
6754            .verification_complete();
6755    }
6756
6757    /// return true if bg hash verification is complete
6758    /// return false if bg hash verification has not completed yet
6759    /// if hash verification failed, a panic will occur
6760    pub fn has_initial_accounts_hash_verification_completed(&self) -> bool {
6761        self.rc
6762            .accounts
6763            .accounts_db
6764            .verify_accounts_hash_in_bg
6765            .check_complete()
6766    }
6767
6768    pub fn get_snapshot_storages(&self, base_slot: Option<Slot>) -> SnapshotStorages {
6769        self.rc
6770            .accounts
6771            .accounts_db
6772            .get_snapshot_storages(self.slot(), base_slot, None)
6773            .0
6774    }
6775
6776    #[must_use]
6777    fn verify_hash(&self) -> bool {
6778        assert!(self.is_frozen());
6779        let calculated_hash = self.hash_internal_state();
6780        let expected_hash = self.hash();
6781
6782        if calculated_hash == expected_hash {
6783            true
6784        } else {
6785            warn!(
6786                "verify failed: slot: {}, {} (calculated) != {} (expected)",
6787                self.slot(),
6788                calculated_hash,
6789                expected_hash
6790            );
6791            false
6792        }
6793    }
6794
6795    pub fn verify_transaction(
6796        &self,
6797        tx: VersionedTransaction,
6798        verification_mode: TransactionVerificationMode,
6799    ) -> Result<SanitizedTransaction> {
6800        let sanitized_tx = {
6801            let size =
6802                bincode::serialized_size(&tx).map_err(|_| TransactionError::SanitizeFailure)?;
6803            if size > PACKET_DATA_SIZE as u64 {
6804                return Err(TransactionError::SanitizeFailure);
6805            }
6806            let message_hash = if verification_mode == TransactionVerificationMode::FullVerification
6807            {
6808                tx.verify_and_hash_message()?
6809            } else {
6810                tx.message.hash()
6811            };
6812
6813            SanitizedTransaction::try_create(
6814                tx,
6815                message_hash,
6816                None,
6817                self,
6818                self.feature_set
6819                    .is_active(&feature_set::require_static_program_ids_in_transaction::ID),
6820            )
6821        }?;
6822
6823        if verification_mode == TransactionVerificationMode::HashAndVerifyPrecompiles
6824            || verification_mode == TransactionVerificationMode::FullVerification
6825        {
6826            sanitized_tx.verify_precompiles(&self.feature_set)?;
6827        }
6828
6829        Ok(sanitized_tx)
6830    }
6831
6832    /// only called at startup vs steady-state runtime
6833    fn calculate_capitalization(&self, debug_verify: bool) -> u64 {
6834        let can_cached_slot_be_unflushed = true; // implied yes
6835        self.rc.accounts.calculate_capitalization(
6836            &self.ancestors,
6837            self.slot(),
6838            can_cached_slot_be_unflushed,
6839            debug_verify,
6840            self.epoch_schedule(),
6841            &self.rent_collector,
6842        )
6843    }
6844
6845    /// only called at startup vs steady-state runtime
6846    pub fn calculate_and_verify_capitalization(&self, debug_verify: bool) -> bool {
6847        let calculated = self.calculate_capitalization(debug_verify);
6848                *self.inflation.write().unwrap() = Inflation::full();
6849        let expected = self.capitalization();
6850        if calculated == expected {
6851            true
6852        } else {
6853            warn!(
6854                "Capitalization mismatch: calculated: {} != expected: {}",
6855                calculated, expected
6856            );
6857            false
6858        }
6859    }
6860
6861    /// Forcibly overwrites current capitalization by actually recalculating accounts' balances.
6862    /// This should only be used for developing purposes.
6863    pub fn set_capitalization(&self) -> u64 {
6864        let old = self.capitalization();
6865        let debug_verify = true;
6866        self.capitalization
6867            .store(self.calculate_capitalization(debug_verify), Relaxed);
6868        old
6869    }
6870
6871    pub fn get_accounts_hash(&self) -> Hash {
6872        self.rc.accounts.accounts_db.get_accounts_hash(self.slot)
6873    }
6874
6875    pub fn get_thread_pool(&self) -> &ThreadPool {
6876        &self.rc.accounts.accounts_db.thread_pool_clean
6877    }
6878
6879    pub fn load_account_into_read_cache(&self, key: &Pubkey) {
6880        self.rc
6881            .accounts
6882            .accounts_db
6883            .load_account_into_read_cache(&self.ancestors, key);
6884    }
6885
6886    pub fn update_accounts_hash_with_index_option(
6887        &self,
6888        use_index: bool,
6889        mut debug_verify: bool,
6890        is_startup: bool,
6891    ) -> Hash {
6892        let (hash, total_lamports) = self
6893            .rc
6894            .accounts
6895            .accounts_db
6896            .update_accounts_hash_with_index_option(
6897                use_index,
6898                debug_verify,
6899                self.slot(),
6900                &self.ancestors,
6901                Some(self.capitalization()),
6902                false,
6903                self.epoch_schedule(),
6904                &self.rent_collector,
6905                is_startup,
6906            );
6907        if total_lamports != self.capitalization() {
6908            datapoint_info!(
6909                "capitalization_mismatch",
6910                ("slot", self.slot(), i64),
6911                ("calculated_lamports", total_lamports, i64),
6912                ("capitalization", self.capitalization(), i64),
6913            );
6914
6915            if !debug_verify {
6916                // cap mismatch detected. It has been logged to metrics above.
6917                // Run both versions of the calculation to attempt to get more info.
6918                debug_verify = true;
6919                self.rc
6920                    .accounts
6921                    .accounts_db
6922                    .update_accounts_hash_with_index_option(
6923                        use_index,
6924                        debug_verify,
6925                        self.slot(),
6926                        &self.ancestors,
6927                        Some(self.capitalization()),
6928                        false,
6929                        self.epoch_schedule(),
6930                        &self.rent_collector,
6931                        is_startup,
6932                    );
6933            }
6934
6935            panic!(
6936                "capitalization_mismatch. slot: {}, calculated_lamports: {}, capitalization: {}",
6937                self.slot(),
6938                total_lamports,
6939                self.capitalization()
6940            );
6941        }
6942        hash
6943    }
6944
6945    pub fn update_accounts_hash(&self) -> Hash {
6946        self.update_accounts_hash_with_index_option(true, false, false)
6947    }
6948
6949    /// A snapshot bank should be purged of 0 lamport accounts which are not part of the hash
6950    /// calculation and could shield other real accounts.
6951    pub fn verify_snapshot_bank(
6952        &self,
6953        test_hash_calculation: bool,
6954        accounts_db_skip_shrink: bool,
6955        last_full_snapshot_slot: Option<Slot>,
6956    ) -> bool {
6957        let mut clean_time = Measure::start("clean");
6958        if !accounts_db_skip_shrink && self.slot() > 0 {
6959            info!("cleaning..");
6960            self.clean_accounts(true, true, last_full_snapshot_slot);
6961        }
6962        clean_time.stop();
6963
6964        let mut shrink_all_slots_time = Measure::start("shrink_all_slots");
6965        if !accounts_db_skip_shrink && self.slot() > 0 {
6966            info!("shrinking..");
6967            self.shrink_all_slots(true, last_full_snapshot_slot);
6968        }
6969        shrink_all_slots_time.stop();
6970
6971        let (mut verify, verify_time_us) = if !self.rc.accounts.accounts_db.skip_initial_hash_calc {
6972            info!("verify_bank_hash..");
6973            let mut verify_time = Measure::start("verify_bank_hash");
6974            let verify = self.verify_bank_hash(VerifyBankHash {
6975                test_hash_calculation,
6976                can_cached_slot_be_unflushed: false,
6977                ignore_mismatch: false,
6978                require_rooted_bank: false,
6979                run_in_background: true,
6980                store_hash_raw_data_for_debug: false,
6981            });
6982            verify_time.stop();
6983            (verify, verify_time.as_us())
6984        } else {
6985            self.rc
6986                .accounts
6987                .accounts_db
6988                .verify_accounts_hash_in_bg
6989                .verification_complete();
6990            (true, 0)
6991        };
6992
6993        info!("verify_hash..");
6994        let mut verify2_time = Measure::start("verify_hash");
6995        // Order and short-circuiting is significant; verify_hash requires a valid bank hash
6996        verify = verify && self.verify_hash();
6997        verify2_time.stop();
6998
6999        datapoint_info!(
7000            "verify_snapshot_bank",
7001            ("clean_us", clean_time.as_us(), i64),
7002            ("shrink_all_slots_us", shrink_all_slots_time.as_us(), i64),
7003            ("verify_bank_hash_us", verify_time_us, i64),
7004            ("verify_hash_us", verify2_time.as_us(), i64),
7005        );
7006
7007        verify
7008    }
7009
7010    /// Return the number of hashes per tick
7011    pub fn hashes_per_tick(&self) -> &Option<u64> {
7012        &self.hashes_per_tick
7013    }
7014
7015    /// Return the number of ticks per slot
7016    pub fn ticks_per_slot(&self) -> u64 {
7017        self.ticks_per_slot
7018    }
7019
7020    /// Return the number of slots per year
7021    pub fn slots_per_year(&self) -> f64 {
7022        self.slots_per_year
7023    }
7024
7025    /// Return the number of ticks since genesis.
7026    pub fn tick_height(&self) -> u64 {
7027        self.tick_height.load(Relaxed)
7028    }
7029
7030    /// Return the inflation parameters of the Bank
7031    pub fn inflation(&self) -> Inflation {
7032        *self.inflation.read().unwrap()
7033    }
7034
7035    pub fn rent_collector(&self) -> &RentCollector {
7036        &self.rent_collector
7037    }
7038
7039    /// Return the total capitalization of the Bank
7040    pub fn capitalization(&self) -> u64 {
7041        self.capitalization.load(Relaxed)
7042    }
7043
7044    /// Return this bank's max_tick_height
7045    pub fn max_tick_height(&self) -> u64 {
7046        self.max_tick_height
7047    }
7048
7049    /// Return the block_height of this bank
7050    pub fn block_height(&self) -> u64 {
7051        self.block_height
7052    }
7053
7054    /// Return the number of slots per epoch for the given epoch
7055    pub fn get_slots_in_epoch(&self, epoch: Epoch) -> u64 {
7056        self.epoch_schedule().get_slots_in_epoch(epoch)
7057    }
7058
7059    /// returns the epoch for which this bank's leader_schedule_slot_offset and slot would
7060    ///  need to cache leader_schedule
7061    pub fn get_leader_schedule_epoch(&self, slot: Slot) -> Epoch {
7062        self.epoch_schedule().get_leader_schedule_epoch(slot)
7063    }
7064
7065    /// a bank-level cache of vote accounts and stake delegation info
7066    fn update_stakes_cache(
7067        &self,
7068        txs: &[SanitizedTransaction],
7069        execution_results: &[TransactionExecutionResult],
7070        loaded_txs: &[TransactionLoadResult],
7071    ) {
7072        for (i, ((load_result, _load_nonce), tx)) in loaded_txs.iter().zip(txs).enumerate() {
7073            if let (Ok(loaded_transaction), true) = (
7074                load_result,
7075                execution_results[i].was_executed_successfully(),
7076            ) {
7077                // note that this could get timed to: self.rc.accounts.accounts_db.stats.stakes_cache_check_and_store_us,
7078                //  but this code path is captured separately in ExecuteTimingType::UpdateStakesCacheUs
7079                let message = tx.message();
7080                for (_i, (pubkey, account)) in
7081                    (0..message.account_keys().len()).zip(loaded_transaction.accounts.iter())
7082                {
7083                    self.stakes_cache.check_and_store(pubkey, account);
7084                }
7085            }
7086        }
7087    }
7088
7089    pub fn staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
7090        self.stakes_cache.stakes().staked_nodes()
7091    }
7092
7093    /// current vote accounts for this bank along with the stake
7094    ///   attributed to each account
7095    pub fn vote_accounts(&self) -> Arc<VoteAccountsHashMap> {
7096        let stakes = self.stakes_cache.stakes();
7097        Arc::from(stakes.vote_accounts())
7098    }
7099
7100    /// Vote account for the given vote account pubkey.
7101    pub fn get_vote_account(&self, vote_account: &Pubkey) -> Option<VoteAccount> {
7102        let stakes = self.stakes_cache.stakes();
7103        let vote_account = stakes.vote_accounts().get(vote_account)?;
7104        Some(vote_account.clone())
7105    }
7106
7107    /// Get the EpochStakes for a given epoch
7108    pub fn epoch_stakes(&self, epoch: Epoch) -> Option<&EpochStakes> {
7109        self.epoch_stakes.get(&epoch)
7110    }
7111
7112    pub fn epoch_stakes_map(&self) -> &HashMap<Epoch, EpochStakes> {
7113        &self.epoch_stakes
7114    }
7115
7116    pub fn epoch_staked_nodes(&self, epoch: Epoch) -> Option<Arc<HashMap<Pubkey, u64>>> {
7117        Some(self.epoch_stakes.get(&epoch)?.stakes().staked_nodes())
7118    }
7119
7120    /// vote accounts for the specific epoch along with the stake
7121    ///   attributed to each account
7122    pub fn epoch_vote_accounts(&self, epoch: Epoch) -> Option<&VoteAccountsHashMap> {
7123        let epoch_stakes = self.epoch_stakes.get(&epoch)?.stakes();
7124        Some(epoch_stakes.vote_accounts().as_ref())
7125    }
7126
7127    /// Get the fixed authorized voter for the given vote account for the
7128    /// current epoch
7129    pub fn epoch_authorized_voter(&self, vote_account: &Pubkey) -> Option<&Pubkey> {
7130        self.epoch_stakes
7131            .get(&self.epoch)
7132            .expect("Epoch stakes for bank's own epoch must exist")
7133            .epoch_authorized_voters()
7134            .get(vote_account)
7135    }
7136
7137    /// Get the fixed set of vote accounts for the given node id for the
7138    /// current epoch
7139    pub fn epoch_vote_accounts_for_node_id(&self, node_id: &Pubkey) -> Option<&NodeVoteAccounts> {
7140        self.epoch_stakes
7141            .get(&self.epoch)
7142            .expect("Epoch stakes for bank's own epoch must exist")
7143            .node_id_to_vote_accounts()
7144            .get(node_id)
7145    }
7146
7147    /// Get the fixed total stake of all vote accounts for current epoch
7148    pub fn total_epoch_stake(&self) -> u64 {
7149        self.epoch_stakes
7150            .get(&self.epoch)
7151            .expect("Epoch stakes for bank's own epoch must exist")
7152            .total_stake()
7153    }
7154
7155    /// Get the fixed stake of the given vote account for the current epoch
7156    pub fn epoch_vote_account_stake(&self, vote_account: &Pubkey) -> u64 {
7157        *self
7158            .epoch_vote_accounts(self.epoch())
7159            .expect("Bank epoch vote accounts must contain entry for the bank's own epoch")
7160            .get(vote_account)
7161            .map(|(stake, _)| stake)
7162            .unwrap_or(&0)
7163    }
7164
7165    /// given a slot, return the epoch and offset into the epoch this slot falls
7166    /// e.g. with a fixed number for slots_per_epoch, the calculation is simply:
7167    ///
7168    ///  ( slot/slots_per_epoch, slot % slots_per_epoch )
7169    ///
7170    pub fn get_epoch_and_slot_index(&self, slot: Slot) -> (Epoch, SlotIndex) {
7171        self.epoch_schedule().get_epoch_and_slot_index(slot)
7172    }
7173
7174    pub fn get_epoch_info(&self) -> EpochInfo {
7175        let absolute_slot = self.slot();
7176        let block_height = self.block_height();
7177        let (epoch, slot_index) = self.get_epoch_and_slot_index(absolute_slot);
7178        let slots_in_epoch = self.get_slots_in_epoch(epoch);
7179        let transaction_count = Some(self.transaction_count());
7180        EpochInfo {
7181            epoch,
7182            slot_index,
7183            slots_in_epoch,
7184            absolute_slot,
7185            block_height,
7186            transaction_count,
7187        }
7188    }
7189
7190    pub fn is_empty(&self) -> bool {
7191        !self.is_delta.load(Relaxed)
7192    }
7193
7194    /// Add an instruction processor to intercept instructions before the dynamic loader.
7195    pub fn add_builtin(
7196        &mut self,
7197        name: &str,
7198        program_id: &Pubkey,
7199        process_instruction: ProcessInstructionWithContext,
7200    ) {
7201        debug!("Adding program {} under {:?}", name, program_id);
7202        self.add_builtin_account(name, program_id, false);
7203        if let Some(entry) = self
7204            .builtin_programs
7205            .vec
7206            .iter_mut()
7207            .find(|entry| entry.program_id == *program_id)
7208        {
7209            entry.process_instruction = process_instruction;
7210        } else {
7211            self.builtin_programs.vec.push(BuiltinProgram {
7212                program_id: *program_id,
7213                process_instruction,
7214            });
7215        }
7216        debug!("Added program {} under {:?}", name, program_id);
7217    }
7218
7219    /// Remove a builtin instruction processor if it already exists
7220    pub fn remove_builtin(&mut self, program_id: &Pubkey) {
7221        debug!("Removing program {}", program_id);
7222        // Don't remove the account since the bank expects the account state to
7223        // be idempotent
7224        if let Some(position) = self
7225            .builtin_programs
7226            .vec
7227            .iter()
7228            .position(|entry| entry.program_id == *program_id)
7229        {
7230            self.builtin_programs.vec.remove(position);
7231        }
7232        debug!("Removed program {}", program_id);
7233    }
7234
7235    pub fn add_precompile(&mut self, program_id: &Pubkey) {
7236        debug!("Adding precompiled program {}", program_id);
7237        self.add_precompiled_account(program_id);
7238        debug!("Added precompiled program {:?}", program_id);
7239    }
7240
7241    pub fn clean_accounts(
7242        &self,
7243        skip_last: bool,
7244        is_startup: bool,
7245        last_full_snapshot_slot: Option<Slot>,
7246    ) {
7247        // Don't clean the slot we're snapshotting because it may have zero-lamport
7248        // accounts that were included in the bank delta hash when the bank was frozen,
7249        // and if we clean them here, any newly created snapshot's hash for this bank
7250        // may not match the frozen hash.
7251        //
7252        // So when we're snapshotting, set `skip_last` to true so the highest slot to clean is
7253        // lowered by one.
7254        let highest_slot_to_clean = skip_last.then(|| self.slot().saturating_sub(1));
7255
7256        self.rc.accounts.accounts_db.clean_accounts(
7257            highest_slot_to_clean,
7258            is_startup,
7259            last_full_snapshot_slot,
7260        );
7261    }
7262
7263    pub fn shrink_all_slots(&self, is_startup: bool, last_full_snapshot_slot: Option<Slot>) {
7264        self.rc
7265            .accounts
7266            .accounts_db
7267            .shrink_all_slots(is_startup, last_full_snapshot_slot);
7268    }
7269
7270    pub fn print_accounts_stats(&self) {
7271        self.rc.accounts.accounts_db.print_accounts_stats("");
7272    }
7273
7274    pub fn process_stale_slot_with_budget(
7275        &self,
7276        mut consumed_budget: usize,
7277        budget_recovery_delta: usize,
7278    ) -> usize {
7279        if consumed_budget == 0 {
7280            let shrunken_account_count = self.rc.accounts.accounts_db.process_stale_slot_v1();
7281            if shrunken_account_count > 0 {
7282                datapoint_info!(
7283                    "stale_slot_shrink",
7284                    ("accounts", shrunken_account_count, i64)
7285                );
7286                consumed_budget += shrunken_account_count;
7287            }
7288        }
7289        consumed_budget.saturating_sub(budget_recovery_delta)
7290    }
7291
7292    pub fn bank_tranaction_count_fix_enabled(&self) -> bool {
7293        self.feature_set
7294            .is_active(&feature_set::bank_tranaction_count_fix::id())
7295    }
7296
7297    pub fn shrink_candidate_slots(&self) -> usize {
7298        self.rc.accounts.accounts_db.shrink_candidate_slots()
7299    }
7300
7301    pub fn no_overflow_rent_distribution_enabled(&self) -> bool {
7302        self.feature_set
7303            .is_active(&feature_set::no_overflow_rent_distribution::id())
7304    }
7305
7306    pub fn versioned_tx_message_enabled(&self) -> bool {
7307        self.feature_set
7308            .is_active(&feature_set::versioned_tx_message_enabled::id())
7309    }
7310
7311    pub fn credits_auto_rewind(&self) -> bool {
7312        self.feature_set
7313            .is_active(&feature_set::credits_auto_rewind::id())
7314    }
7315
7316    pub fn send_to_tpu_vote_port_enabled(&self) -> bool {
7317        self.feature_set
7318            .is_active(&feature_set::send_to_tpu_vote_port::id())
7319    }
7320
7321    fn preserve_rent_epoch_for_rent_exempt_accounts(&self) -> bool {
7322        self.feature_set
7323            .is_active(&feature_set::preserve_rent_epoch_for_rent_exempt_accounts::id())
7324    }
7325
7326    pub fn concurrent_replay_of_forks(&self) -> bool {
7327        self.feature_set
7328            .is_active(&feature_set::concurrent_replay_of_forks::id())
7329    }
7330
7331    pub fn read_cost_tracker(&self) -> LockResult<RwLockReadGuard<CostTracker>> {
7332        self.cost_tracker.read()
7333    }
7334
7335    pub fn write_cost_tracker(&self) -> LockResult<RwLockWriteGuard<CostTracker>> {
7336        self.cost_tracker.write()
7337    }
7338
7339    // Check if the wallclock time from bank creation to now has exceeded the allotted
7340    // time for transaction processing
7341    pub fn should_bank_still_be_processing_txs(
7342        bank_creation_time: &Instant,
7343        max_tx_ingestion_nanos: u128,
7344    ) -> bool {
7345        // Do this check outside of the poh lock, hence not a method on PohRecorder
7346        bank_creation_time.elapsed().as_nanos() <= max_tx_ingestion_nanos
7347    }
7348
7349    pub fn deactivate_feature(&mut self, id: &Pubkey) {
7350        let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
7351        feature_set.active.remove(id);
7352        feature_set.inactive.insert(*id);
7353        self.feature_set = Arc::new(feature_set);
7354    }
7355
7356    pub fn activate_feature(&mut self, id: &Pubkey) {
7357        let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
7358        feature_set.inactive.remove(id);
7359        feature_set.active.insert(*id, 0);
7360        self.feature_set = Arc::new(feature_set);
7361    }
7362
7363    pub fn fill_bank_with_ticks_for_tests(&self) {
7364        if self.tick_height.load(Relaxed) < self.max_tick_height {
7365            let last_blockhash = self.last_blockhash();
7366            while self.last_blockhash() == last_blockhash {
7367                self.register_tick(&Hash::new_unique())
7368            }
7369        } else {
7370            warn!("Bank already reached max tick height, cannot fill it with more ticks");
7371        }
7372    }
7373
7374    // This is called from snapshot restore AND for each epoch boundary
7375    // The entire code path herein must be idempotent
7376    fn apply_feature_activations(
7377        &mut self,
7378        caller: ApplyFeatureActivationsCaller,
7379        debug_do_not_add_builtins: bool,
7380    ) {
7381        use ApplyFeatureActivationsCaller::*;
7382        let allow_new_activations = match caller {
7383            FinishInit => false,
7384            NewFromParent => true,
7385            WarpFromParent => false,
7386        };
7387        let new_feature_activations = self.compute_active_feature_set(allow_new_activations);
7388
7389        if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
7390            *self.inflation.write().unwrap() = Inflation::full();
7391            self.fee_rate_governor.burn_percent = 50; // 50% fee burn
7392            self.rent_collector.rent.burn_percent = 50; // 50% rent burn
7393        }
7394
7395        if !new_feature_activations.is_disjoint(&self.feature_set.full_inflation_features_enabled())
7396        {
7397            *self.inflation.write().unwrap() = Inflation::full();
7398            self.fee_rate_governor.burn_percent = 50; // 50% fee burn
7399            self.rent_collector.rent.burn_percent = 50; // 50% rent burn
7400        }
7401
7402        if new_feature_activations.contains(&feature_set::safe_token_v3_4_0::id()) {
7403            self.replace_program_account(
7404                &inline_safe_token::id(),
7405                &inline_safe_token::program_v3_4_0::id(),
7406                "bank-apply_safe_token_v3_4_0",
7407            );
7408        }
7409
7410        if new_feature_activations.contains(&feature_set::safe_associated_token_account_v1_1_0::id())
7411        {
7412            self.replace_program_account(
7413                &inline_safe_associated_token_account::id(),
7414                &inline_safe_associated_token_account::program_v1_1_0::id(),
7415                "bank-apply_safe_associated_token_account_v1_1_0",
7416            );
7417        }
7418
7419        if !debug_do_not_add_builtins {
7420            self.apply_builtin_program_feature_transitions(
7421                allow_new_activations,
7422                &new_feature_activations,
7423            );
7424            self.reconfigure_token2_native_mint();
7425        }
7426        self.ensure_no_storage_rewards_pool();
7427
7428        if new_feature_activations.contains(&feature_set::cap_accounts_data_len::id()) {
7429            const ACCOUNTS_DATA_LEN: u64 = 50_000_000_000;
7430            self.accounts_data_size_initial = ACCOUNTS_DATA_LEN;
7431        }
7432    }
7433
7434    fn adjust_sysvar_balance_for_rent(&self, account: &mut AccountSharedData) {
7435        account.set_lamports(
7436            self.get_minimum_balance_for_rent_exemption(account.data().len())
7437                .max(account.lamports()),
7438        );
7439    }
7440
7441    // Compute the active feature set based on the current bank state, and return the set of newly activated features
7442    fn compute_active_feature_set(&mut self, allow_new_activations: bool) -> HashSet<Pubkey> {
7443        let mut active = self.feature_set.active.clone();
7444        let mut inactive = HashSet::new();
7445        let mut newly_activated = HashSet::new();
7446        let slot = self.slot();
7447
7448        for feature_id in &self.feature_set.inactive {
7449            let mut activated = None;
7450            if let Some(mut account) = self.get_account_with_fixed_root(feature_id) {
7451                if let Some(mut feature) = feature::from_account(&account) {
7452                    match feature.activated_at {
7453                        None => {
7454                            if allow_new_activations {
7455                                // Feature has been requested, activate it now
7456                                feature.activated_at = Some(slot);
7457                                if feature::to_account(&feature, &mut account).is_some() {
7458                                    self.store_account(feature_id, &account);
7459                                }
7460                                newly_activated.insert(*feature_id);
7461                                activated = Some(slot);
7462                                info!("Feature {} activated at slot {}", feature_id, slot);
7463                            }
7464                        }
7465                        Some(activation_slot) => {
7466                            if slot >= activation_slot {
7467                                // Feature is already active
7468                                activated = Some(activation_slot);
7469                            }
7470                        }
7471                    }
7472                }
7473            }
7474            if let Some(slot) = activated {
7475                active.insert(*feature_id, slot);
7476            } else {
7477                inactive.insert(*feature_id);
7478            }
7479        }
7480
7481        self.feature_set = Arc::new(FeatureSet { active, inactive });
7482        newly_activated
7483    }
7484
7485    fn apply_builtin_program_feature_transitions(
7486        &mut self,
7487        only_apply_transitions_for_new_features: bool,
7488        new_feature_activations: &HashSet<Pubkey>,
7489    ) {
7490        let feature_set = self.feature_set.clone();
7491        let should_apply_action_for_feature_transition = |feature_id: &Pubkey| -> bool {
7492            if only_apply_transitions_for_new_features {
7493                new_feature_activations.contains(feature_id)
7494            } else {
7495                feature_set.is_active(feature_id)
7496            }
7497        };
7498
7499        let builtin_feature_transitions = self.builtin_feature_transitions.clone();
7500        for transition in builtin_feature_transitions.iter() {
7501            if let Some(builtin_action) =
7502                transition.to_action(&should_apply_action_for_feature_transition)
7503            {
7504                match builtin_action {
7505                    BuiltinAction::Add(builtin) => self.add_builtin(
7506                        &builtin.name,
7507                        &builtin.id,
7508                        builtin.process_instruction_with_context,
7509                    ),
7510                    BuiltinAction::Remove(program_id) => self.remove_builtin(&program_id),
7511                }
7512            }
7513        }
7514
7515        for precompile in get_precompiles() {
7516            #[allow(clippy::blocks_in_if_conditions)]
7517            if precompile.feature.map_or(false, |ref feature_id| {
7518                self.feature_set.is_active(feature_id)
7519            }) {
7520                self.add_precompile(&precompile.program_id);
7521            }
7522        }
7523    }
7524
7525    fn replace_program_account(
7526        &mut self,
7527        old_address: &Pubkey,
7528        new_address: &Pubkey,
7529        datapoint_name: &'static str,
7530    ) {
7531        if let Some(old_account) = self.get_account_with_fixed_root(old_address) {
7532            if let Some(new_account) = self.get_account_with_fixed_root(new_address) {
7533                datapoint_info!(datapoint_name, ("slot", self.slot, i64));
7534
7535                // Burn lamports in the old account
7536                self.capitalization
7537                    .fetch_sub(old_account.lamports(), Relaxed);
7538
7539                // Transfer new account to old account
7540                self.store_account(old_address, &new_account);
7541
7542                // Clear new account
7543                self.store_account(new_address, &AccountSharedData::default());
7544
7545                self.remove_executor(old_address);
7546
7547                self.calculate_and_update_accounts_data_size_delta_off_chain(
7548                    old_account.data().len(),
7549                    new_account.data().len(),
7550                );
7551            }
7552        }
7553    }
7554
7555    fn reconfigure_token2_native_mint(&mut self) {
7556        let reconfigure_token2_native_mint = match self.cluster_type() {
7557            ClusterType::Development => true,
7558            ClusterType::Devnet => true,
7559            ClusterType::Testnet => self.epoch() == 93,
7560            ClusterType::MainnetBeta => self.epoch() == 9999999,
7561        };
7562
7563        if reconfigure_token2_native_mint {
7564            let mut native_mint_account = solana_sdk::account::AccountSharedData::from(Account {
7565                owner: inline_safe_token::id(),
7566                data: inline_safe_token::native_mint::ACCOUNT_DATA.to_vec(),
7567                lamports: sol_to_lamports(1.),
7568                executable: false,
7569                rent_epoch: self.epoch() + 1,
7570            });
7571
7572            // As a workaround for
7573            // https://github.com/fair-exchange/safecoin-program-library/issues/374, ensure that the
7574            // safe-token 2 native mint account is owned by the safe-token 2 program.
7575            let old_account_data_size;
7576            let store = if let Some(existing_native_mint_account) =
7577                self.get_account_with_fixed_root(&inline_safe_token::native_mint::id())
7578            {
7579                old_account_data_size = existing_native_mint_account.data().len();
7580                if existing_native_mint_account.owner() == &solana_sdk::system_program::id() {
7581                    native_mint_account.set_lamports(existing_native_mint_account.lamports());
7582                    true
7583                } else {
7584                    false
7585                }
7586            } else {
7587                old_account_data_size = 0;
7588                self.capitalization
7589                    .fetch_add(native_mint_account.lamports(), Relaxed);
7590                true
7591            };
7592
7593            if store {
7594                self.store_account(&inline_safe_token::native_mint::id(), &native_mint_account);
7595                self.calculate_and_update_accounts_data_size_delta_off_chain(
7596                    old_account_data_size,
7597                    native_mint_account.data().len(),
7598                );
7599            }
7600        }
7601    }
7602
7603    fn ensure_no_storage_rewards_pool(&mut self) {
7604        let purge_window_epoch = match self.cluster_type() {
7605            ClusterType::Development => false,
7606            // never do this for devnet; we're pristine here. :)
7607            ClusterType::Devnet => false,
7608            // schedule to remove at testnet/tds
7609            ClusterType::Testnet => self.epoch() == 93,
7610            // never do this for stable; we're pristine here. :)
7611            ClusterType::MainnetBeta => false,
7612        };
7613
7614        if purge_window_epoch {
7615            for reward_pubkey in self.rewards_pool_pubkeys.iter() {
7616                if let Some(mut reward_account) = self.get_account_with_fixed_root(reward_pubkey) {
7617                    if reward_account.lamports() == u64::MAX {
7618                        reward_account.set_lamports(0);
7619                        self.store_account(reward_pubkey, &reward_account);
7620                        // Adjust capitalization.... it has been wrapping, reducing the real capitalization by 1-lamport
7621                        self.capitalization.fetch_add(1, Relaxed);
7622                        info!(
7623                            "purged rewards pool account: {}, new capitalization: {}",
7624                            reward_pubkey,
7625                            self.capitalization()
7626                        );
7627                    }
7628                };
7629            }
7630        }
7631    }
7632
7633    /// Get all the accounts for this bank and calculate stats
7634    pub fn get_total_accounts_stats(&self) -> ScanResult<TotalAccountsStats> {
7635        let accounts = self.get_all_accounts_with_modified_slots()?;
7636        Ok(self.calculate_total_accounts_stats(
7637            accounts
7638                .iter()
7639                .map(|(pubkey, account, _slot)| (pubkey, account)),
7640        ))
7641    }
7642
7643    /// Given all the accounts for a bank, calculate stats
7644    pub fn calculate_total_accounts_stats<'a>(
7645        &self,
7646        accounts: impl Iterator<Item = (&'a Pubkey, &'a AccountSharedData)>,
7647    ) -> TotalAccountsStats {
7648        let rent_collector = self.rent_collector();
7649        let mut total_accounts_stats = TotalAccountsStats::default();
7650        accounts.for_each(|(pubkey, account)| {
7651            let data_len = account.data().len();
7652            total_accounts_stats.num_accounts += 1;
7653            total_accounts_stats.data_len += data_len;
7654
7655            if account.executable() {
7656                total_accounts_stats.num_executable_accounts += 1;
7657                total_accounts_stats.executable_data_len += data_len;
7658            }
7659
7660            if !rent_collector.should_collect_rent(pubkey, account)
7661                || rent_collector.get_rent_due(account).is_exempt()
7662            {
7663                total_accounts_stats.num_rent_exempt_accounts += 1;
7664            } else {
7665                total_accounts_stats.num_rent_paying_accounts += 1;
7666                total_accounts_stats.lamports_in_rent_paying_accounts += account.lamports();
7667                if data_len == 0 {
7668                    total_accounts_stats.num_rent_paying_accounts_without_data += 1;
7669                }
7670            }
7671        });
7672
7673        total_accounts_stats
7674    }
7675}
7676
7677/// Compute how much an account has changed size.  This function is useful when the data size delta
7678/// needs to be computed and passed to an `update_accounts_data_size_delta` function.
7679fn calculate_data_size_delta(old_data_size: usize, new_data_size: usize) -> i64 {
7680    assert!(old_data_size <= i64::MAX as usize);
7681    assert!(new_data_size <= i64::MAX as usize);
7682    let old_data_size = old_data_size as i64;
7683    let new_data_size = new_data_size as i64;
7684
7685    new_data_size.saturating_sub(old_data_size)
7686}
7687
7688/// Since `apply_feature_activations()` has different behavior depending on its caller, enumerate
7689/// those callers explicitly.
7690#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7691enum ApplyFeatureActivationsCaller {
7692    FinishInit,
7693    NewFromParent,
7694    WarpFromParent,
7695}
7696
7697/// Return the computed values from `collect_rent_from_accounts()`
7698///
7699/// Since `collect_rent_from_accounts()` is running in parallel, instead of updating the
7700/// atomics/shared data inside this function, return those values in this struct for the caller to
7701/// process later.
7702#[derive(Debug, Default)]
7703struct CollectRentFromAccountsInfo {
7704    rent_collected_info: CollectedInfo,
7705    rent_rewards: Vec<(Pubkey, RewardInfo)>,
7706    rewrites_skipped: Vec<(Pubkey, Hash)>,
7707    time_collecting_rent_us: u64,
7708    time_hashing_skipped_rewrites_us: u64,
7709    time_storing_accounts_us: u64,
7710    num_accounts: usize,
7711}
7712
7713/// Return the computed values—of each iteration in the parallel loop inside
7714/// `collect_rent_in_partition()`—and then perform a reduce on all of them.
7715#[derive(Debug, Default)]
7716struct CollectRentInPartitionInfo {
7717    rent_collected: u64,
7718    accounts_data_size_reclaimed: u64,
7719    rent_rewards: Vec<(Pubkey, RewardInfo)>,
7720    rewrites_skipped: Vec<(Pubkey, Hash)>,
7721    time_loading_accounts_us: u64,
7722    time_collecting_rent_us: u64,
7723    time_hashing_skipped_rewrites_us: u64,
7724    time_storing_accounts_us: u64,
7725    num_accounts: usize,
7726}
7727
7728impl CollectRentInPartitionInfo {
7729    /// Create a new `CollectRentInPartitionInfo` from the results of loading accounts and
7730    /// collecting rent on them.
7731    #[must_use]
7732    fn new(info: CollectRentFromAccountsInfo, time_loading_accounts: Duration) -> Self {
7733        Self {
7734            rent_collected: info.rent_collected_info.rent_amount,
7735            accounts_data_size_reclaimed: info.rent_collected_info.account_data_len_reclaimed,
7736            rent_rewards: info.rent_rewards,
7737            rewrites_skipped: info.rewrites_skipped,
7738            time_loading_accounts_us: time_loading_accounts.as_micros() as u64,
7739            time_collecting_rent_us: info.time_collecting_rent_us,
7740            time_hashing_skipped_rewrites_us: info.time_hashing_skipped_rewrites_us,
7741            time_storing_accounts_us: info.time_storing_accounts_us,
7742            num_accounts: info.num_accounts,
7743        }
7744    }
7745
7746    /// Reduce (i.e. 'combine') two `CollectRentInPartitionInfo`s into one.
7747    ///
7748    /// This fn is used by `collect_rent_in_partition()` as the reduce step (of map-reduce) in its
7749    /// parallel loop of rent collection.
7750    #[must_use]
7751    fn reduce(lhs: Self, rhs: Self) -> Self {
7752        Self {
7753            rent_collected: lhs.rent_collected.saturating_add(rhs.rent_collected),
7754            accounts_data_size_reclaimed: lhs
7755                .accounts_data_size_reclaimed
7756                .saturating_add(rhs.accounts_data_size_reclaimed),
7757            rent_rewards: [lhs.rent_rewards, rhs.rent_rewards].concat(),
7758            rewrites_skipped: [lhs.rewrites_skipped, rhs.rewrites_skipped].concat(),
7759            time_loading_accounts_us: lhs
7760                .time_loading_accounts_us
7761                .saturating_add(rhs.time_loading_accounts_us),
7762            time_collecting_rent_us: lhs
7763                .time_collecting_rent_us
7764                .saturating_add(rhs.time_collecting_rent_us),
7765            time_hashing_skipped_rewrites_us: lhs
7766                .time_hashing_skipped_rewrites_us
7767                .saturating_add(rhs.time_hashing_skipped_rewrites_us),
7768            time_storing_accounts_us: lhs
7769                .time_storing_accounts_us
7770                .saturating_add(rhs.time_storing_accounts_us),
7771            num_accounts: lhs.num_accounts.saturating_add(rhs.num_accounts),
7772        }
7773    }
7774}
7775
7776/// Struct to collect stats when scanning all accounts in `get_total_accounts_stats()`
7777#[derive(Debug, Default, Copy, Clone)]
7778pub struct TotalAccountsStats {
7779    /// Total number of accounts
7780    pub num_accounts: usize,
7781    /// Total data size of all accounts
7782    pub data_len: usize,
7783
7784    /// Total number of executable accounts
7785    pub num_executable_accounts: usize,
7786    /// Total data size of executable accounts
7787    pub executable_data_len: usize,
7788
7789    /// Total number of rent exempt accounts
7790    pub num_rent_exempt_accounts: usize,
7791    /// Total number of rent paying accounts
7792    pub num_rent_paying_accounts: usize,
7793    /// Total number of rent paying accounts without data
7794    pub num_rent_paying_accounts_without_data: usize,
7795    /// Total amount of lamports in rent paying accounts
7796    pub lamports_in_rent_paying_accounts: u64,
7797}
7798
7799impl Drop for Bank {
7800    fn drop(&mut self) {
7801        if let Some(drop_callback) = self.drop_callback.read().unwrap().0.as_ref() {
7802            drop_callback.callback(self);
7803        } else {
7804            // Default case for tests
7805            self.rc
7806                .accounts
7807                .accounts_db
7808                .purge_slot(self.slot(), self.bank_id(), false);
7809        }
7810    }
7811}
7812
7813/// utility function used for testing and benchmarking.
7814pub mod test_utils {
7815    use {super::Bank, solana_sdk::hash::hashv};
7816    pub fn goto_end_of_slot(bank: &mut Bank) {
7817        let mut tick_hash = bank.last_blockhash();
7818        loop {
7819            tick_hash = hashv(&[tick_hash.as_ref(), &[42]]);
7820            bank.register_tick(&tick_hash);
7821            if tick_hash == bank.last_blockhash() {
7822                bank.freeze();
7823                return;
7824            }
7825        }
7826    }
7827}
7828
7829#[cfg(test)]
7830pub(crate) mod tests {
7831    #[allow(deprecated)]
7832    use solana_sdk::sysvar::fees::Fees;
7833    use {
7834        super::*,
7835        crate::{
7836            accounts_background_service::{AbsRequestHandler, SendDroppedBankCallback},
7837            accounts_db::DEFAULT_ACCOUNTS_SHRINK_RATIO,
7838            accounts_index::{AccountIndex, AccountSecondaryIndexes, ScanError, ITER_BATCH_SIZE},
7839            ancestors::Ancestors,
7840            genesis_utils::{
7841                self, activate_all_features, bootstrap_validator_stake_lamports,
7842                create_genesis_config_with_leader, create_genesis_config_with_vote_accounts,
7843                genesis_sysvar_and_builtin_program_lamports, GenesisConfigInfo,
7844                ValidatorVoteKeypairs,
7845            },
7846            rent_paying_accounts_by_partition::RentPayingAccountsByPartition,
7847            status_cache::MAX_CACHE_ENTRIES,
7848        },
7849        crossbeam_channel::{bounded, unbounded},
7850        rand::Rng,
7851        solana_program_runtime::{
7852            compute_budget::MAX_COMPUTE_UNIT_LIMIT,
7853            executor_cache::Executor,
7854            invoke_context::InvokeContext,
7855            prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType},
7856        },
7857        solana_sdk::{
7858            account::Account,
7859            bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
7860            clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT, MAX_RECENT_BLOCKHASHES},
7861            compute_budget::ComputeBudgetInstruction,
7862            entrypoint::MAX_PERMITTED_DATA_INCREASE,
7863            epoch_schedule::MINIMUM_SLOTS_PER_EPOCH,
7864            feature::Feature,
7865            genesis_config::create_genesis_config,
7866            hash,
7867            instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
7868            message::{Message, MessageHeader},
7869            nonce,
7870            poh_config::PohConfig,
7871            program::MAX_RETURN_DATA,
7872            rent::Rent,
7873            signature::{keypair_from_seed, Keypair, Signer},
7874            stake::{
7875                instruction as stake_instruction,
7876                state::{Authorized, Delegation, Lockup, Stake},
7877            },
7878            system_instruction::{self, SystemError, MAX_PERMITTED_DATA_LENGTH},
7879            system_program,
7880            timing::duration_as_s,
7881            transaction_context::InstructionContext,
7882        },
7883        solana_vote_program::{
7884            vote_instruction,
7885            vote_state::{
7886                self, BlockTimestamp, Vote, VoteInit, VoteState, VoteStateVersions,
7887                MAX_LOCKOUT_HISTORY,
7888            },
7889        },
7890        std::{
7891            result, str::FromStr, sync::atomic::Ordering::Release, thread::Builder, time::Duration,
7892        },
7893        test_utils::goto_end_of_slot,
7894    };
7895
7896    fn new_sanitized_message(
7897        instructions: &[Instruction],
7898        payer: Option<&Pubkey>,
7899    ) -> SanitizedMessage {
7900        Message::new(instructions, payer).try_into().unwrap()
7901    }
7902
7903    fn new_execution_result(
7904        status: Result<()>,
7905        nonce: Option<&NonceFull>,
7906    ) -> TransactionExecutionResult {
7907        TransactionExecutionResult::Executed {
7908            details: TransactionExecutionDetails {
7909                status,
7910                log_messages: None,
7911                inner_instructions: None,
7912                durable_nonce_fee: nonce.map(DurableNonceFee::from),
7913                return_data: None,
7914                executed_units: 0,
7915                accounts_data_len_delta: 0,
7916            },
7917            executors: Rc::new(RefCell::new(Executors::default())),
7918        }
7919    }
7920
7921    #[test]
7922    fn test_nonce_info() {
7923        let lamports_per_signature = 42;
7924
7925        let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
7926        let nonce_address = nonce_authority.pubkey();
7927        let from = keypair_from_seed(&[1; 32]).unwrap();
7928        let from_address = from.pubkey();
7929        let to_address = Pubkey::new_unique();
7930
7931        let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique());
7932        let nonce_account = AccountSharedData::new_data(
7933            43,
7934            &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data::new(
7935                Pubkey::default(),
7936                durable_nonce,
7937                lamports_per_signature,
7938            ))),
7939            &system_program::id(),
7940        )
7941        .unwrap();
7942        let from_account = AccountSharedData::new(44, 0, &Pubkey::default());
7943        let to_account = AccountSharedData::new(45, 0, &Pubkey::default());
7944        let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
7945
7946        const TEST_RENT_DEBIT: u64 = 1;
7947        let rent_collected_nonce_account = {
7948            let mut account = nonce_account.clone();
7949            account.set_lamports(nonce_account.lamports() - TEST_RENT_DEBIT);
7950            account
7951        };
7952        let rent_collected_from_account = {
7953            let mut account = from_account.clone();
7954            account.set_lamports(from_account.lamports() - TEST_RENT_DEBIT);
7955            account
7956        };
7957
7958        let instructions = vec![
7959            system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
7960            system_instruction::transfer(&from_address, &to_address, 42),
7961        ];
7962
7963        // NoncePartial create + NonceInfo impl
7964        let partial = NoncePartial::new(nonce_address, rent_collected_nonce_account.clone());
7965        assert_eq!(*partial.address(), nonce_address);
7966        assert_eq!(*partial.account(), rent_collected_nonce_account);
7967        assert_eq!(
7968            partial.lamports_per_signature(),
7969            Some(lamports_per_signature)
7970        );
7971        assert_eq!(partial.fee_payer_account(), None);
7972
7973        // Add rent debits to ensure the rollback captures accounts without rent fees
7974        let mut rent_debits = RentDebits::default();
7975        rent_debits.insert(
7976            &from_address,
7977            TEST_RENT_DEBIT,
7978            rent_collected_from_account.lamports(),
7979        );
7980        rent_debits.insert(
7981            &nonce_address,
7982            TEST_RENT_DEBIT,
7983            rent_collected_nonce_account.lamports(),
7984        );
7985
7986        // NonceFull create + NonceInfo impl
7987        {
7988            let message = new_sanitized_message(&instructions, Some(&from_address));
7989            let accounts = [
7990                (
7991                    *message.account_keys().get(0).unwrap(),
7992                    rent_collected_from_account.clone(),
7993                ),
7994                (
7995                    *message.account_keys().get(1).unwrap(),
7996                    rent_collected_nonce_account.clone(),
7997                ),
7998                (*message.account_keys().get(2).unwrap(), to_account.clone()),
7999                (
8000                    *message.account_keys().get(3).unwrap(),
8001                    recent_blockhashes_sysvar_account.clone(),
8002                ),
8003            ];
8004
8005            let full = NonceFull::from_partial(partial.clone(), &message, &accounts, &rent_debits)
8006                .unwrap();
8007            assert_eq!(*full.address(), nonce_address);
8008            assert_eq!(*full.account(), rent_collected_nonce_account);
8009            assert_eq!(full.lamports_per_signature(), Some(lamports_per_signature));
8010            assert_eq!(
8011                full.fee_payer_account(),
8012                Some(&from_account),
8013                "rent debit should be refunded in captured fee account"
8014            );
8015        }
8016
8017        // Nonce account is fee-payer
8018        {
8019            let message = new_sanitized_message(&instructions, Some(&nonce_address));
8020            let accounts = [
8021                (
8022                    *message.account_keys().get(0).unwrap(),
8023                    rent_collected_nonce_account,
8024                ),
8025                (
8026                    *message.account_keys().get(1).unwrap(),
8027                    rent_collected_from_account,
8028                ),
8029                (*message.account_keys().get(2).unwrap(), to_account),
8030                (
8031                    *message.account_keys().get(3).unwrap(),
8032                    recent_blockhashes_sysvar_account,
8033                ),
8034            ];
8035
8036            let full = NonceFull::from_partial(partial.clone(), &message, &accounts, &rent_debits)
8037                .unwrap();
8038            assert_eq!(*full.address(), nonce_address);
8039            assert_eq!(*full.account(), nonce_account);
8040            assert_eq!(full.lamports_per_signature(), Some(lamports_per_signature));
8041            assert_eq!(full.fee_payer_account(), None);
8042        }
8043
8044        // NonceFull create, fee-payer not in account_keys fails
8045        {
8046            let message = new_sanitized_message(&instructions, Some(&nonce_address));
8047            assert_eq!(
8048                NonceFull::from_partial(partial, &message, &[], &RentDebits::default())
8049                    .unwrap_err(),
8050                TransactionError::AccountNotFound,
8051            );
8052        }
8053    }
8054
8055    #[test]
8056    fn test_bank_unix_timestamp_from_genesis() {
8057        let (genesis_config, _mint_keypair) = create_genesis_config(1);
8058        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
8059
8060        assert_eq!(
8061            genesis_config.creation_time,
8062            bank.unix_timestamp_from_genesis()
8063        );
8064        let slots_per_sec = 1.0
8065            / (duration_as_s(&genesis_config.poh_config.target_tick_duration)
8066                * genesis_config.ticks_per_slot as f32);
8067
8068        for _i in 0..slots_per_sec as usize + 1 {
8069            bank = Arc::new(new_from_parent(&bank));
8070        }
8071
8072        assert!(bank.unix_timestamp_from_genesis() - genesis_config.creation_time >= 1);
8073    }
8074
8075    #[test]
8076    #[allow(clippy::float_cmp)]
8077    fn test_bank_new() {
8078        let dummy_leader_pubkey = solana_sdk::pubkey::new_rand();
8079        let dummy_leader_stake_lamports = bootstrap_validator_stake_lamports();
8080        let mint_lamports = 10_000;
8081        let GenesisConfigInfo {
8082            mut genesis_config,
8083            mint_keypair,
8084            voting_keypair,
8085            ..
8086        } = create_genesis_config_with_leader(
8087            mint_lamports,
8088            &dummy_leader_pubkey,
8089            dummy_leader_stake_lamports,
8090        );
8091
8092        genesis_config.rent = Rent {
8093            lamports_per_byte_year: 5,
8094            exemption_threshold: 1.2,
8095            burn_percent: 5,
8096        };
8097
8098        let bank = Bank::new_for_tests(&genesis_config);
8099        assert_eq!(bank.get_balance(&mint_keypair.pubkey()), mint_lamports);
8100        assert_eq!(
8101            bank.get_balance(&voting_keypair.pubkey()),
8102            dummy_leader_stake_lamports /* 1 token goes to the vote account associated with dummy_leader_lamports */
8103        );
8104
8105        let rent_account = bank.get_account(&sysvar::rent::id()).unwrap();
8106        let rent = from_account::<sysvar::rent::Rent, _>(&rent_account).unwrap();
8107
8108        assert_eq!(rent.burn_percent, 5);
8109        assert_eq!(rent.exemption_threshold, 1.2);
8110        assert_eq!(rent.lamports_per_byte_year, 5);
8111    }
8112
8113    fn create_simple_test_bank(lamports: u64) -> Bank {
8114        let (genesis_config, _mint_keypair) = create_genesis_config(lamports);
8115        Bank::new_for_tests(&genesis_config)
8116    }
8117
8118    fn create_simple_test_arc_bank(lamports: u64) -> Arc<Bank> {
8119        Arc::new(create_simple_test_bank(lamports))
8120    }
8121
8122    #[test]
8123    fn test_bank_block_height() {
8124        let bank0 = create_simple_test_arc_bank(1);
8125        assert_eq!(bank0.block_height(), 0);
8126        let bank1 = Arc::new(new_from_parent(&bank0));
8127        assert_eq!(bank1.block_height(), 1);
8128    }
8129
8130    #[test]
8131    fn test_bank_update_epoch_stakes() {
8132        impl Bank {
8133            fn epoch_stake_keys(&self) -> Vec<Epoch> {
8134                let mut keys: Vec<Epoch> = self.epoch_stakes.keys().copied().collect();
8135                keys.sort_unstable();
8136                keys
8137            }
8138
8139            fn epoch_stake_key_info(&self) -> (Epoch, Epoch, usize) {
8140                let mut keys: Vec<Epoch> = self.epoch_stakes.keys().copied().collect();
8141                keys.sort_unstable();
8142                (*keys.first().unwrap(), *keys.last().unwrap(), keys.len())
8143            }
8144        }
8145
8146        let mut bank = create_simple_test_bank(100_000);
8147
8148        let initial_epochs = bank.epoch_stake_keys();
8149        assert_eq!(initial_epochs, vec![0, 1]);
8150
8151        for existing_epoch in &initial_epochs {
8152            bank.update_epoch_stakes(*existing_epoch);
8153            assert_eq!(bank.epoch_stake_keys(), initial_epochs);
8154        }
8155
8156        for epoch in (initial_epochs.len() as Epoch)..MAX_LEADER_SCHEDULE_STAKES {
8157            bank.update_epoch_stakes(epoch);
8158            assert_eq!(bank.epoch_stakes.len() as Epoch, epoch + 1);
8159        }
8160
8161        assert_eq!(
8162            bank.epoch_stake_key_info(),
8163            (
8164                0,
8165                MAX_LEADER_SCHEDULE_STAKES - 1,
8166                MAX_LEADER_SCHEDULE_STAKES as usize
8167            )
8168        );
8169
8170        bank.update_epoch_stakes(MAX_LEADER_SCHEDULE_STAKES);
8171        assert_eq!(
8172            bank.epoch_stake_key_info(),
8173            (
8174                0,
8175                MAX_LEADER_SCHEDULE_STAKES,
8176                MAX_LEADER_SCHEDULE_STAKES as usize + 1
8177            )
8178        );
8179
8180        bank.update_epoch_stakes(MAX_LEADER_SCHEDULE_STAKES + 1);
8181        assert_eq!(
8182            bank.epoch_stake_key_info(),
8183            (
8184                1,
8185                MAX_LEADER_SCHEDULE_STAKES + 1,
8186                MAX_LEADER_SCHEDULE_STAKES as usize + 1
8187            )
8188        );
8189    }
8190
8191    fn bank0_sysvar_delta() -> u64 {
8192        const SLOT_HISTORY_SYSVAR_MIN_BALANCE: u64 = 913_326_000;
8193        SLOT_HISTORY_SYSVAR_MIN_BALANCE
8194    }
8195
8196    fn bank1_sysvar_delta() -> u64 {
8197        const SLOT_HASHES_SYSVAR_MIN_BALANCE: u64 = 143_487_360;
8198        SLOT_HASHES_SYSVAR_MIN_BALANCE
8199    }
8200
8201    #[test]
8202    fn test_bank_capitalization() {
8203        let bank0 = Arc::new(Bank::new_for_tests(&GenesisConfig {
8204            accounts: (0..42)
8205                .map(|_| {
8206                    (
8207                        solana_sdk::pubkey::new_rand(),
8208                        Account::new(42, 0, &Pubkey::default()),
8209                    )
8210                })
8211                .collect(),
8212            cluster_type: ClusterType::MainnetBeta,
8213            ..GenesisConfig::default()
8214        }));
8215
8216        assert_eq!(
8217            bank0.capitalization(),
8218            42 * 42 + genesis_sysvar_and_builtin_program_lamports(),
8219        );
8220
8221        bank0.freeze();
8222
8223        assert_eq!(
8224            bank0.capitalization(),
8225            42 * 42 + genesis_sysvar_and_builtin_program_lamports() + bank0_sysvar_delta(),
8226        );
8227
8228        let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
8229        assert_eq!(
8230            bank1.capitalization(),
8231            42 * 42
8232                + genesis_sysvar_and_builtin_program_lamports()
8233                + bank0_sysvar_delta()
8234                + bank1_sysvar_delta(),
8235        );
8236    }
8237
8238    fn rent_with_exemption_threshold(exemption_threshold: f64) -> Rent {
8239        Rent {
8240            lamports_per_byte_year: 1,
8241            exemption_threshold,
8242            burn_percent: 10,
8243        }
8244    }
8245
8246    #[test]
8247    /// one thing being tested here is that a failed tx (due to rent collection using up all lamports) followed by rent collection
8248    /// results in the same state as if just rent collection ran (and emptied the accounts that have too few lamports)
8249    fn test_credit_debit_rent_no_side_effect_on_hash() {
8250        solana_logger::setup();
8251
8252        let (mut genesis_config, _mint_keypair) = create_genesis_config(10);
8253
8254        genesis_config.rent = rent_with_exemption_threshold(21.0);
8255
8256        let slot = years_as_slots(
8257            2.0,
8258            &genesis_config.poh_config.target_tick_duration,
8259            genesis_config.ticks_per_slot,
8260        ) as u64;
8261        let root_bank = Arc::new(Bank::new_for_tests(&genesis_config));
8262        let bank = Bank::new_from_parent(&root_bank, &Pubkey::default(), slot);
8263
8264        let root_bank_2 = Arc::new(Bank::new_for_tests(&genesis_config));
8265        let bank_with_success_txs = Bank::new_from_parent(&root_bank_2, &Pubkey::default(), slot);
8266
8267        assert_eq!(bank.last_blockhash(), genesis_config.hash());
8268
8269        let plenty_of_lamports = 264;
8270        let too_few_lamports = 10;
8271        // Initialize credit-debit and credit only accounts
8272        let accounts = [
8273            AccountSharedData::new(plenty_of_lamports, 0, &Pubkey::default()),
8274            AccountSharedData::new(plenty_of_lamports, 1, &Pubkey::default()),
8275            AccountSharedData::new(plenty_of_lamports, 0, &Pubkey::default()),
8276            AccountSharedData::new(plenty_of_lamports, 1, &Pubkey::default()),
8277            // Transaction between these two accounts will fail
8278            AccountSharedData::new(too_few_lamports, 0, &Pubkey::default()),
8279            AccountSharedData::new(too_few_lamports, 1, &Pubkey::default()),
8280        ];
8281
8282        let keypairs = accounts.iter().map(|_| Keypair::new()).collect::<Vec<_>>();
8283        {
8284            // make sure rent and epoch change are such that we collect all lamports in accounts 4 & 5
8285            let mut account_copy = accounts[4].clone();
8286            let expected_rent = bank.rent_collector().collect_from_existing_account(
8287                &keypairs[4].pubkey(),
8288                &mut account_copy,
8289                None,
8290                true, // preserve_rent_epoch_for_rent_exempt_accounts
8291            );
8292            assert_eq!(expected_rent.rent_amount, too_few_lamports);
8293            assert_eq!(account_copy.lamports(), 0);
8294        }
8295
8296        for i in 0..accounts.len() {
8297            let account = &accounts[i];
8298            bank.store_account(&keypairs[i].pubkey(), account);
8299            bank_with_success_txs.store_account(&keypairs[i].pubkey(), account);
8300        }
8301
8302        // Make builtin instruction loader rent exempt
8303        let system_program_id = system_program::id();
8304        let mut system_program_account = bank.get_account(&system_program_id).unwrap();
8305        system_program_account.set_lamports(
8306            bank.get_minimum_balance_for_rent_exemption(system_program_account.data().len()),
8307        );
8308        bank.store_account(&system_program_id, &system_program_account);
8309        bank_with_success_txs.store_account(&system_program_id, &system_program_account);
8310
8311        let t1 = system_transaction::transfer(
8312            &keypairs[0],
8313            &keypairs[1].pubkey(),
8314            1,
8315            genesis_config.hash(),
8316        );
8317        let t2 = system_transaction::transfer(
8318            &keypairs[2],
8319            &keypairs[3].pubkey(),
8320            1,
8321            genesis_config.hash(),
8322        );
8323        // the idea is this transaction will result in both accounts being drained of all lamports due to rent collection
8324        let t3 = system_transaction::transfer(
8325            &keypairs[4],
8326            &keypairs[5].pubkey(),
8327            1,
8328            genesis_config.hash(),
8329        );
8330
8331        let txs = vec![t1.clone(), t2.clone(), t3];
8332        let res = bank.process_transactions(txs.iter());
8333
8334        assert_eq!(res.len(), 3);
8335        assert_eq!(res[0], Ok(()));
8336        assert_eq!(res[1], Ok(()));
8337        assert_eq!(res[2], Err(TransactionError::AccountNotFound));
8338
8339        bank.freeze();
8340
8341        let rwlockguard_bank_hash = bank.hash.read().unwrap();
8342        let bank_hash = rwlockguard_bank_hash.as_ref();
8343
8344        let txs = vec![t2, t1];
8345        let res = bank_with_success_txs.process_transactions(txs.iter());
8346
8347        assert_eq!(res.len(), 2);
8348        assert_eq!(res[0], Ok(()));
8349        assert_eq!(res[1], Ok(()));
8350
8351        bank_with_success_txs.freeze();
8352
8353        let rwlockguard_bank_with_success_txs_hash = bank_with_success_txs.hash.read().unwrap();
8354        let bank_with_success_txs_hash = rwlockguard_bank_with_success_txs_hash.as_ref();
8355
8356        assert_eq!(bank_with_success_txs_hash, bank_hash);
8357    }
8358
8359    fn store_accounts_for_rent_test(
8360        bank: &Bank,
8361        keypairs: &mut [Keypair],
8362        mock_program_id: Pubkey,
8363        generic_rent_due_for_system_account: u64,
8364    ) {
8365        let mut account_pairs: Vec<TransactionAccount> = Vec::with_capacity(keypairs.len() - 1);
8366        account_pairs.push((
8367            keypairs[0].pubkey(),
8368            AccountSharedData::new(
8369                generic_rent_due_for_system_account + 2,
8370                0,
8371                &Pubkey::default(),
8372            ),
8373        ));
8374        account_pairs.push((
8375            keypairs[1].pubkey(),
8376            AccountSharedData::new(
8377                generic_rent_due_for_system_account + 2,
8378                0,
8379                &Pubkey::default(),
8380            ),
8381        ));
8382        account_pairs.push((
8383            keypairs[2].pubkey(),
8384            AccountSharedData::new(
8385                generic_rent_due_for_system_account + 2,
8386                0,
8387                &Pubkey::default(),
8388            ),
8389        ));
8390        account_pairs.push((
8391            keypairs[3].pubkey(),
8392            AccountSharedData::new(
8393                generic_rent_due_for_system_account + 2,
8394                0,
8395                &Pubkey::default(),
8396            ),
8397        ));
8398        account_pairs.push((
8399            keypairs[4].pubkey(),
8400            AccountSharedData::new(10, 0, &Pubkey::default()),
8401        ));
8402        account_pairs.push((
8403            keypairs[5].pubkey(),
8404            AccountSharedData::new(10, 0, &Pubkey::default()),
8405        ));
8406        account_pairs.push((
8407            keypairs[6].pubkey(),
8408            AccountSharedData::new(
8409                (2 * generic_rent_due_for_system_account) + 24,
8410                0,
8411                &Pubkey::default(),
8412            ),
8413        ));
8414
8415        account_pairs.push((
8416            keypairs[8].pubkey(),
8417            AccountSharedData::new(
8418                generic_rent_due_for_system_account + 2 + 929,
8419                0,
8420                &Pubkey::default(),
8421            ),
8422        ));
8423        account_pairs.push((
8424            keypairs[9].pubkey(),
8425            AccountSharedData::new(10, 0, &Pubkey::default()),
8426        ));
8427
8428        // Feeding to MockProgram to test read only rent behaviour
8429        account_pairs.push((
8430            keypairs[10].pubkey(),
8431            AccountSharedData::new(
8432                generic_rent_due_for_system_account + 3,
8433                0,
8434                &Pubkey::default(),
8435            ),
8436        ));
8437        account_pairs.push((
8438            keypairs[11].pubkey(),
8439            AccountSharedData::new(generic_rent_due_for_system_account + 3, 0, &mock_program_id),
8440        ));
8441        account_pairs.push((
8442            keypairs[12].pubkey(),
8443            AccountSharedData::new(generic_rent_due_for_system_account + 3, 0, &mock_program_id),
8444        ));
8445        account_pairs.push((
8446            keypairs[13].pubkey(),
8447            AccountSharedData::new(14, 22, &mock_program_id),
8448        ));
8449
8450        for account_pair in account_pairs.iter() {
8451            bank.store_account(&account_pair.0, &account_pair.1);
8452        }
8453    }
8454
8455    fn create_child_bank_for_rent_test(
8456        root_bank: &Arc<Bank>,
8457        genesis_config: &GenesisConfig,
8458    ) -> Bank {
8459        let mut bank = Bank::new_from_parent(
8460            root_bank,
8461            &Pubkey::default(),
8462            years_as_slots(
8463                2.0,
8464                &genesis_config.poh_config.target_tick_duration,
8465                genesis_config.ticks_per_slot,
8466            ) as u64,
8467        );
8468        bank.rent_collector.slots_per_year = 421_812.0;
8469        bank
8470    }
8471
8472    fn assert_capitalization_diff(bank: &Bank, updater: impl Fn(), asserter: impl Fn(u64, u64)) {
8473        let old = bank.capitalization();
8474        updater();
8475        let new = bank.capitalization();
8476        asserter(old, new);
8477        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
8478    }
8479
8480    #[test]
8481    fn test_store_account_and_update_capitalization_missing() {
8482        let bank = create_simple_test_bank(0);
8483        let pubkey = solana_sdk::pubkey::new_rand();
8484
8485        let some_lamports = 400;
8486        let account = AccountSharedData::new(some_lamports, 0, &system_program::id());
8487
8488        assert_capitalization_diff(
8489            &bank,
8490            || bank.store_account_and_update_capitalization(&pubkey, &account),
8491            |old, new| assert_eq!(old + some_lamports, new),
8492        );
8493        assert_eq!(account, bank.get_account(&pubkey).unwrap());
8494    }
8495
8496    #[test]
8497    fn test_store_account_and_update_capitalization_increased() {
8498        let old_lamports = 400;
8499        let (genesis_config, mint_keypair) = create_genesis_config(old_lamports);
8500        let bank = Bank::new_for_tests(&genesis_config);
8501        let pubkey = mint_keypair.pubkey();
8502
8503        let new_lamports = 500;
8504        let account = AccountSharedData::new(new_lamports, 0, &system_program::id());
8505
8506        assert_capitalization_diff(
8507            &bank,
8508            || bank.store_account_and_update_capitalization(&pubkey, &account),
8509            |old, new| assert_eq!(old + 100, new),
8510        );
8511        assert_eq!(account, bank.get_account(&pubkey).unwrap());
8512    }
8513
8514    #[test]
8515    fn test_store_account_and_update_capitalization_decreased() {
8516        let old_lamports = 400;
8517        let (genesis_config, mint_keypair) = create_genesis_config(old_lamports);
8518        let bank = Bank::new_for_tests(&genesis_config);
8519        let pubkey = mint_keypair.pubkey();
8520
8521        let new_lamports = 100;
8522        let account = AccountSharedData::new(new_lamports, 0, &system_program::id());
8523
8524        assert_capitalization_diff(
8525            &bank,
8526            || bank.store_account_and_update_capitalization(&pubkey, &account),
8527            |old, new| assert_eq!(old - 300, new),
8528        );
8529        assert_eq!(account, bank.get_account(&pubkey).unwrap());
8530    }
8531
8532    #[test]
8533    fn test_store_account_and_update_capitalization_unchanged() {
8534        let lamports = 400;
8535        let (genesis_config, mint_keypair) = create_genesis_config(lamports);
8536        let bank = Bank::new_for_tests(&genesis_config);
8537        let pubkey = mint_keypair.pubkey();
8538
8539        let account = AccountSharedData::new(lamports, 1, &system_program::id());
8540
8541        assert_capitalization_diff(
8542            &bank,
8543            || bank.store_account_and_update_capitalization(&pubkey, &account),
8544            |old, new| assert_eq!(old, new),
8545        );
8546        assert_eq!(account, bank.get_account(&pubkey).unwrap());
8547    }
8548
8549    #[test]
8550    #[ignore]
8551    fn test_rent_distribution() {
8552        solana_logger::setup();
8553
8554        let bootstrap_validator_pubkey = solana_sdk::pubkey::new_rand();
8555        let bootstrap_validator_stake_lamports = 30;
8556        let mut genesis_config = create_genesis_config_with_leader(
8557            10,
8558            &bootstrap_validator_pubkey,
8559            bootstrap_validator_stake_lamports,
8560        )
8561        .genesis_config;
8562        // While we are preventing new accounts left in a rent-paying state, not quite ready to rip
8563        // out all the rent assessment tests. Just deactivate the feature for now.
8564        genesis_config
8565            .accounts
8566            .remove(&feature_set::require_rent_exempt_accounts::id())
8567            .unwrap();
8568
8569        genesis_config.epoch_schedule = EpochSchedule::custom(
8570            MINIMUM_SLOTS_PER_EPOCH,
8571            genesis_config.epoch_schedule.leader_schedule_slot_offset,
8572            false,
8573        );
8574
8575        genesis_config.rent = rent_with_exemption_threshold(2.0);
8576
8577        let rent = Rent::free();
8578
8579        let validator_1_pubkey = solana_sdk::pubkey::new_rand();
8580        let validator_1_stake_lamports = 20;
8581        let validator_1_staking_keypair = Keypair::new();
8582        let validator_1_voting_keypair = Keypair::new();
8583
8584        let validator_1_vote_account = vote_state::create_account(
8585            &validator_1_voting_keypair.pubkey(),
8586            &validator_1_pubkey,
8587            0,
8588            validator_1_stake_lamports,
8589        );
8590
8591        let validator_1_stake_account = stake_state::create_account(
8592            &validator_1_staking_keypair.pubkey(),
8593            &validator_1_voting_keypair.pubkey(),
8594            &validator_1_vote_account,
8595            &rent,
8596            validator_1_stake_lamports,
8597        );
8598
8599        genesis_config.accounts.insert(
8600            validator_1_pubkey,
8601            Account::new(42, 0, &system_program::id()),
8602        );
8603        genesis_config.accounts.insert(
8604            validator_1_staking_keypair.pubkey(),
8605            Account::from(validator_1_stake_account),
8606        );
8607        genesis_config.accounts.insert(
8608            validator_1_voting_keypair.pubkey(),
8609            Account::from(validator_1_vote_account),
8610        );
8611
8612        let validator_2_pubkey = solana_sdk::pubkey::new_rand();
8613        let validator_2_stake_lamports = 20;
8614        let validator_2_staking_keypair = Keypair::new();
8615        let validator_2_voting_keypair = Keypair::new();
8616
8617        let validator_2_vote_account = vote_state::create_account(
8618            &validator_2_voting_keypair.pubkey(),
8619            &validator_2_pubkey,
8620            0,
8621            validator_2_stake_lamports,
8622        );
8623
8624        let validator_2_stake_account = stake_state::create_account(
8625            &validator_2_staking_keypair.pubkey(),
8626            &validator_2_voting_keypair.pubkey(),
8627            &validator_2_vote_account,
8628            &rent,
8629            validator_2_stake_lamports,
8630        );
8631
8632        genesis_config.accounts.insert(
8633            validator_2_pubkey,
8634            Account::new(42, 0, &system_program::id()),
8635        );
8636        genesis_config.accounts.insert(
8637            validator_2_staking_keypair.pubkey(),
8638            Account::from(validator_2_stake_account),
8639        );
8640        genesis_config.accounts.insert(
8641            validator_2_voting_keypair.pubkey(),
8642            Account::from(validator_2_vote_account),
8643        );
8644
8645        let validator_3_pubkey = solana_sdk::pubkey::new_rand();
8646        let validator_3_stake_lamports = 30;
8647        let validator_3_staking_keypair = Keypair::new();
8648        let validator_3_voting_keypair = Keypair::new();
8649
8650        let validator_3_vote_account = vote_state::create_account(
8651            &validator_3_voting_keypair.pubkey(),
8652            &validator_3_pubkey,
8653            0,
8654            validator_3_stake_lamports,
8655        );
8656
8657        let validator_3_stake_account = stake_state::create_account(
8658            &validator_3_staking_keypair.pubkey(),
8659            &validator_3_voting_keypair.pubkey(),
8660            &validator_3_vote_account,
8661            &rent,
8662            validator_3_stake_lamports,
8663        );
8664
8665        genesis_config.accounts.insert(
8666            validator_3_pubkey,
8667            Account::new(42, 0, &system_program::id()),
8668        );
8669        genesis_config.accounts.insert(
8670            validator_3_staking_keypair.pubkey(),
8671            Account::from(validator_3_stake_account),
8672        );
8673        genesis_config.accounts.insert(
8674            validator_3_voting_keypair.pubkey(),
8675            Account::from(validator_3_vote_account),
8676        );
8677
8678        genesis_config.rent = rent_with_exemption_threshold(10.0);
8679
8680        let mut bank = Bank::new_for_tests(&genesis_config);
8681        // Enable rent collection
8682        bank.rent_collector.epoch = 5;
8683        bank.rent_collector.slots_per_year = 192.0;
8684
8685        let payer = Keypair::new();
8686        let payer_account = AccountSharedData::new(400, 0, &system_program::id());
8687        bank.store_account_and_update_capitalization(&payer.pubkey(), &payer_account);
8688
8689        let payee = Keypair::new();
8690        let payee_account = AccountSharedData::new(70, 1, &system_program::id());
8691        bank.store_account_and_update_capitalization(&payee.pubkey(), &payee_account);
8692
8693        let bootstrap_validator_initial_balance = bank.get_balance(&bootstrap_validator_pubkey);
8694
8695        let tx = system_transaction::transfer(&payer, &payee.pubkey(), 180, genesis_config.hash());
8696
8697        let result = bank.process_transaction(&tx);
8698        assert_eq!(result, Ok(()));
8699
8700        let mut total_rent_deducted = 0;
8701
8702        // 400 - 128(Rent) - 180(Transfer)
8703        assert_eq!(bank.get_balance(&payer.pubkey()), 92);
8704        total_rent_deducted += 128;
8705
8706        // 70 - 70(Rent) + 180(Transfer) - 21(Rent)
8707        assert_eq!(bank.get_balance(&payee.pubkey()), 159);
8708        total_rent_deducted += 70 + 21;
8709
8710        let previous_capitalization = bank.capitalization.load(Relaxed);
8711
8712        bank.freeze();
8713
8714        assert_eq!(bank.collected_rent.load(Relaxed), total_rent_deducted);
8715
8716        let burned_portion =
8717            total_rent_deducted * u64::from(bank.rent_collector.rent.burn_percent) / 100;
8718        let rent_to_be_distributed = total_rent_deducted - burned_portion;
8719
8720        let bootstrap_validator_portion =
8721            ((bootstrap_validator_stake_lamports * rent_to_be_distributed) as f64 / 100.0) as u64
8722                + 1; // Leftover lamport
8723        assert_eq!(
8724            bank.get_balance(&bootstrap_validator_pubkey),
8725            bootstrap_validator_portion + bootstrap_validator_initial_balance
8726        );
8727
8728        // Since, validator 1 and validator 2 has equal smallest stake, it comes down to comparison
8729        // between their pubkey.
8730        let tweak_1 = u64::from(validator_1_pubkey > validator_2_pubkey);
8731        let validator_1_portion =
8732            ((validator_1_stake_lamports * rent_to_be_distributed) as f64 / 100.0) as u64 + tweak_1;
8733        assert_eq!(
8734            bank.get_balance(&validator_1_pubkey),
8735            validator_1_portion + 42 - tweak_1,
8736        );
8737
8738        // Since, validator 1 and validator 2 has equal smallest stake, it comes down to comparison
8739        // between their pubkey.
8740        let tweak_2 = u64::from(validator_2_pubkey > validator_1_pubkey);
8741        let validator_2_portion =
8742            ((validator_2_stake_lamports * rent_to_be_distributed) as f64 / 100.0) as u64 + tweak_2;
8743        assert_eq!(
8744            bank.get_balance(&validator_2_pubkey),
8745            validator_2_portion + 42 - tweak_2,
8746        );
8747
8748        let validator_3_portion =
8749            ((validator_3_stake_lamports * rent_to_be_distributed) as f64 / 100.0) as u64 + 1;
8750        assert_eq!(
8751            bank.get_balance(&validator_3_pubkey),
8752            validator_3_portion + 42
8753        );
8754
8755        let current_capitalization = bank.capitalization.load(Relaxed);
8756
8757        // only slot history is newly created
8758        let sysvar_and_builtin_program_delta =
8759            min_rent_excempt_balance_for_sysvars(&bank, &[sysvar::slot_history::id()]);
8760        assert_eq!(
8761            previous_capitalization - (current_capitalization - sysvar_and_builtin_program_delta),
8762            burned_portion
8763        );
8764
8765        assert!(bank.calculate_and_verify_capitalization(true));
8766
8767        assert_eq!(
8768            rent_to_be_distributed,
8769            bank.rewards
8770                .read()
8771                .unwrap()
8772                .iter()
8773                .map(|(address, reward)| {
8774                    if reward.lamports > 0 {
8775                        assert_eq!(reward.reward_type, RewardType::Rent);
8776                        if *address == validator_2_pubkey {
8777                            assert_eq!(reward.post_balance, validator_2_portion + 42 - tweak_2);
8778                        } else if *address == validator_3_pubkey {
8779                            assert_eq!(reward.post_balance, validator_3_portion + 42);
8780                        }
8781                        reward.lamports as u64
8782                    } else {
8783                        0
8784                    }
8785                })
8786                .sum::<u64>()
8787        );
8788    }
8789
8790    #[test]
8791    fn test_distribute_rent_to_validators_overflow() {
8792        solana_logger::setup();
8793
8794        // These values are taken from the real cluster (testnet)
8795        const RENT_TO_BE_DISTRIBUTED: u64 = 120_525;
8796        const VALIDATOR_STAKE: u64 = 374_999_998_287_840;
8797
8798        let validator_pubkey = solana_sdk::pubkey::new_rand();
8799        let mut genesis_config =
8800            create_genesis_config_with_leader(10, &validator_pubkey, VALIDATOR_STAKE)
8801                .genesis_config;
8802
8803        let bank = Bank::new_for_tests(&genesis_config);
8804        let old_validator_lamports = bank.get_balance(&validator_pubkey);
8805        bank.distribute_rent_to_validators(&bank.vote_accounts(), RENT_TO_BE_DISTRIBUTED);
8806        let new_validator_lamports = bank.get_balance(&validator_pubkey);
8807        assert_eq!(
8808            new_validator_lamports,
8809            old_validator_lamports + RENT_TO_BE_DISTRIBUTED
8810        );
8811
8812        genesis_config
8813            .accounts
8814            .remove(&feature_set::no_overflow_rent_distribution::id())
8815            .unwrap();
8816        let bank = std::panic::AssertUnwindSafe(Bank::new_for_tests(&genesis_config));
8817        let old_validator_lamports = bank.get_balance(&validator_pubkey);
8818        let new_validator_lamports = std::panic::catch_unwind(|| {
8819            bank.distribute_rent_to_validators(&bank.vote_accounts(), RENT_TO_BE_DISTRIBUTED);
8820            bank.get_balance(&validator_pubkey)
8821        });
8822
8823        if let Ok(new_validator_lamports) = new_validator_lamports {
8824            info!("asserting overflowing incorrect rent distribution");
8825            assert_ne!(
8826                new_validator_lamports,
8827                old_validator_lamports + RENT_TO_BE_DISTRIBUTED
8828            );
8829        } else {
8830            info!("NOT-asserting overflowing incorrect rent distribution");
8831        }
8832    }
8833
8834    #[test]
8835    fn test_rent_exempt_executable_account() {
8836        let (mut genesis_config, mint_keypair) = create_genesis_config(100_000);
8837        genesis_config.rent = rent_with_exemption_threshold(1000.0);
8838
8839        let root_bank = Arc::new(Bank::new_for_tests(&genesis_config));
8840        let bank = create_child_bank_for_rent_test(&root_bank, &genesis_config);
8841
8842        let account_pubkey = solana_sdk::pubkey::new_rand();
8843        let account_balance = 1;
8844        let mut account =
8845            AccountSharedData::new(account_balance, 0, &solana_sdk::pubkey::new_rand());
8846        account.set_executable(true);
8847        bank.store_account(&account_pubkey, &account);
8848
8849        let transfer_lamports = 1;
8850        let tx = system_transaction::transfer(
8851            &mint_keypair,
8852            &account_pubkey,
8853            transfer_lamports,
8854            genesis_config.hash(),
8855        );
8856
8857        assert_eq!(
8858            bank.process_transaction(&tx),
8859            Err(TransactionError::InvalidWritableAccount)
8860        );
8861        assert_eq!(bank.get_balance(&account_pubkey), account_balance);
8862    }
8863
8864    #[test]
8865    #[ignore]
8866    #[allow(clippy::cognitive_complexity)]
8867    fn test_rent_complex() {
8868        solana_logger::setup();
8869        let mock_program_id = Pubkey::from([2u8; 32]);
8870
8871        #[derive(Serialize, Deserialize)]
8872        enum MockInstruction {
8873            Deduction,
8874        }
8875
8876        fn mock_process_instruction(
8877            _first_instruction_account: usize,
8878            invoke_context: &mut InvokeContext,
8879        ) -> result::Result<(), InstructionError> {
8880            let transaction_context = &invoke_context.transaction_context;
8881            let instruction_context = transaction_context.get_current_instruction_context()?;
8882            let instruction_data = instruction_context.get_instruction_data();
8883            if let Ok(instruction) = bincode::deserialize(instruction_data) {
8884                match instruction {
8885                    MockInstruction::Deduction => {
8886                        instruction_context
8887                            .try_borrow_instruction_account(transaction_context, 1)?
8888                            .checked_add_lamports(1)?;
8889                        instruction_context
8890                            .try_borrow_instruction_account(transaction_context, 2)?
8891                            .checked_sub_lamports(1)?;
8892                        Ok(())
8893                    }
8894                }
8895            } else {
8896                Err(InstructionError::InvalidInstructionData)
8897            }
8898        }
8899
8900        let (mut genesis_config, _mint_keypair) = create_genesis_config(10);
8901        let mut keypairs: Vec<Keypair> = Vec::with_capacity(14);
8902        for _i in 0..14 {
8903            keypairs.push(Keypair::new());
8904        }
8905
8906        genesis_config.rent = rent_with_exemption_threshold(1000.0);
8907
8908        let root_bank = Bank::new_for_tests(&genesis_config);
8909        // until we completely transition to the eager rent collection,
8910        // we must ensure lazy rent collection doens't get broken!
8911        root_bank.restore_old_behavior_for_fragile_tests();
8912        let root_bank = Arc::new(root_bank);
8913        let mut bank = create_child_bank_for_rent_test(&root_bank, &genesis_config);
8914        bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
8915
8916        assert_eq!(bank.last_blockhash(), genesis_config.hash());
8917
8918        let slots_elapsed: u64 = (0..=bank.epoch)
8919            .map(|epoch| {
8920                bank.rent_collector
8921                    .epoch_schedule
8922                    .get_slots_in_epoch(epoch + 1)
8923            })
8924            .sum();
8925        let generic_rent_due_for_system_account = bank
8926            .rent_collector
8927            .rent
8928            .due(
8929                bank.get_minimum_balance_for_rent_exemption(0) - 1,
8930                0,
8931                slots_elapsed as f64 / bank.rent_collector.slots_per_year,
8932            )
8933            .lamports();
8934
8935        store_accounts_for_rent_test(
8936            &bank,
8937            &mut keypairs,
8938            mock_program_id,
8939            generic_rent_due_for_system_account,
8940        );
8941
8942        let magic_rent_number = 131; // yuck, derive this value programmatically one day
8943
8944        let t1 = system_transaction::transfer(
8945            &keypairs[0],
8946            &keypairs[1].pubkey(),
8947            1,
8948            genesis_config.hash(),
8949        );
8950        let t2 = system_transaction::transfer(
8951            &keypairs[2],
8952            &keypairs[3].pubkey(),
8953            1,
8954            genesis_config.hash(),
8955        );
8956        let t3 = system_transaction::transfer(
8957            &keypairs[4],
8958            &keypairs[5].pubkey(),
8959            1,
8960            genesis_config.hash(),
8961        );
8962        let t4 = system_transaction::transfer(
8963            &keypairs[6],
8964            &keypairs[7].pubkey(),
8965            generic_rent_due_for_system_account + 1,
8966            genesis_config.hash(),
8967        );
8968        let t5 = system_transaction::transfer(
8969            &keypairs[8],
8970            &keypairs[9].pubkey(),
8971            929,
8972            genesis_config.hash(),
8973        );
8974
8975        let account_metas = vec![
8976            AccountMeta::new(keypairs[10].pubkey(), true),
8977            AccountMeta::new(keypairs[11].pubkey(), true),
8978            AccountMeta::new(keypairs[12].pubkey(), true),
8979            AccountMeta::new_readonly(keypairs[13].pubkey(), false),
8980        ];
8981        let deduct_instruction = Instruction::new_with_bincode(
8982            mock_program_id,
8983            &MockInstruction::Deduction,
8984            account_metas,
8985        );
8986        let t6 = Transaction::new_signed_with_payer(
8987            &[deduct_instruction],
8988            Some(&keypairs[10].pubkey()),
8989            &[&keypairs[10], &keypairs[11], &keypairs[12]],
8990            genesis_config.hash(),
8991        );
8992
8993        let txs = vec![t6, t5, t1, t2, t3, t4];
8994        let res = bank.process_transactions(txs.iter());
8995
8996        assert_eq!(res.len(), 6);
8997        assert_eq!(res[0], Ok(()));
8998        assert_eq!(res[1], Ok(()));
8999        assert_eq!(res[2], Ok(()));
9000        assert_eq!(res[3], Ok(()));
9001        assert_eq!(res[4], Err(TransactionError::AccountNotFound));
9002        assert_eq!(res[5], Ok(()));
9003
9004        bank.freeze();
9005
9006        let mut rent_collected = 0;
9007
9008        // 48992 - generic_rent_due_for_system_account(Rent) - 1(transfer)
9009        assert_eq!(bank.get_balance(&keypairs[0].pubkey()), 1);
9010        rent_collected += generic_rent_due_for_system_account;
9011
9012        // 48992 - generic_rent_due_for_system_account(Rent) + 1(transfer)
9013        assert_eq!(bank.get_balance(&keypairs[1].pubkey()), 3);
9014        rent_collected += generic_rent_due_for_system_account;
9015
9016        // 48992 - generic_rent_due_for_system_account(Rent) - 1(transfer)
9017        assert_eq!(bank.get_balance(&keypairs[2].pubkey()), 1);
9018        rent_collected += generic_rent_due_for_system_account;
9019
9020        // 48992 - generic_rent_due_for_system_account(Rent) + 1(transfer)
9021        assert_eq!(bank.get_balance(&keypairs[3].pubkey()), 3);
9022        rent_collected += generic_rent_due_for_system_account;
9023
9024        // No rent deducted
9025        assert_eq!(bank.get_balance(&keypairs[4].pubkey()), 10);
9026        assert_eq!(bank.get_balance(&keypairs[5].pubkey()), 10);
9027
9028        // 98004 - generic_rent_due_for_system_account(Rent) - 48991(transfer)
9029        assert_eq!(bank.get_balance(&keypairs[6].pubkey()), 23);
9030        rent_collected += generic_rent_due_for_system_account;
9031
9032        // 0 + 48990(transfer) - magic_rent_number(Rent)
9033        assert_eq!(
9034            bank.get_balance(&keypairs[7].pubkey()),
9035            generic_rent_due_for_system_account + 1 - magic_rent_number
9036        );
9037
9038        // Epoch should be updated
9039        // Rent deducted on store side
9040        let account8 = bank.get_account(&keypairs[7].pubkey()).unwrap();
9041        // Epoch should be set correctly.
9042        assert_eq!(account8.rent_epoch(), bank.epoch + 1);
9043        rent_collected += magic_rent_number;
9044
9045        // 49921 - generic_rent_due_for_system_account(Rent) - 929(Transfer)
9046        assert_eq!(bank.get_balance(&keypairs[8].pubkey()), 2);
9047        rent_collected += generic_rent_due_for_system_account;
9048
9049        let account10 = bank.get_account(&keypairs[9].pubkey()).unwrap();
9050        // Account was overwritten at load time, since it didn't have sufficient balance to pay rent
9051        // Then, at store time we deducted `magic_rent_number` rent for the current epoch, once it has balance
9052        assert_eq!(account10.rent_epoch(), bank.epoch + 1);
9053        // account data is blank now
9054        assert_eq!(account10.data().len(), 0);
9055        // 10 - 10(Rent) + 929(Transfer) - magic_rent_number(Rent)
9056        assert_eq!(account10.lamports(), 929 - magic_rent_number);
9057        rent_collected += magic_rent_number + 10;
9058
9059        // 48993 - generic_rent_due_for_system_account(Rent)
9060        assert_eq!(bank.get_balance(&keypairs[10].pubkey()), 3);
9061        rent_collected += generic_rent_due_for_system_account;
9062
9063        // 48993 - generic_rent_due_for_system_account(Rent) + 1(Addition by program)
9064        assert_eq!(bank.get_balance(&keypairs[11].pubkey()), 4);
9065        rent_collected += generic_rent_due_for_system_account;
9066
9067        // 48993 - generic_rent_due_for_system_account(Rent) - 1(Deduction by program)
9068        assert_eq!(bank.get_balance(&keypairs[12].pubkey()), 2);
9069        rent_collected += generic_rent_due_for_system_account;
9070
9071        // No rent for read-only account
9072        assert_eq!(bank.get_balance(&keypairs[13].pubkey()), 14);
9073
9074        // Bank's collected rent should be sum of rent collected from all accounts
9075        assert_eq!(bank.collected_rent.load(Relaxed), rent_collected);
9076    }
9077
9078    fn test_rent_collection_partitions(bank: &Bank) -> Vec<Partition> {
9079        let partitions = bank.rent_collection_partitions();
9080        let slot = bank.slot();
9081        if slot.saturating_sub(1) == bank.parent_slot() {
9082            let partition = Bank::variable_cycle_partition_from_previous_slot(
9083                bank.epoch_schedule(),
9084                bank.slot(),
9085            );
9086            assert_eq!(
9087                partitions.last().unwrap(),
9088                &partition,
9089                "slot: {}, slots per epoch: {}, partitions: {:?}",
9090                bank.slot(),
9091                bank.epoch_schedule().slots_per_epoch,
9092                partitions
9093            );
9094        }
9095        partitions
9096    }
9097
9098    #[test]
9099    fn test_rent_eager_across_epoch_without_gap() {
9100        let mut bank = create_simple_test_arc_bank(1);
9101        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
9102
9103        bank = Arc::new(new_from_parent(&bank));
9104        assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 32)]);
9105        for _ in 2..32 {
9106            bank = Arc::new(new_from_parent(&bank));
9107        }
9108        assert_eq!(bank.rent_collection_partitions(), vec![(30, 31, 32)]);
9109        bank = Arc::new(new_from_parent(&bank));
9110        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 64)]);
9111    }
9112
9113    #[test]
9114    fn test_rent_eager_across_epoch_without_gap_mnb() {
9115        solana_logger::setup();
9116        let (mut genesis_config, _mint_keypair) = create_genesis_config(1);
9117        genesis_config.cluster_type = ClusterType::MainnetBeta;
9118
9119        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9120        assert_eq!(test_rent_collection_partitions(&bank), vec![(0, 0, 32)]);
9121
9122        bank = Arc::new(new_from_parent(&bank));
9123        assert_eq!(test_rent_collection_partitions(&bank), vec![(0, 1, 32)]);
9124        for _ in 2..32 {
9125            bank = Arc::new(new_from_parent(&bank));
9126        }
9127        assert_eq!(test_rent_collection_partitions(&bank), vec![(30, 31, 32)]);
9128        bank = Arc::new(new_from_parent(&bank));
9129        assert_eq!(test_rent_collection_partitions(&bank), vec![(0, 0, 64)]);
9130    }
9131
9132    #[test]
9133    fn test_rent_eager_across_epoch_with_full_gap() {
9134        let (mut genesis_config, _mint_keypair) = create_genesis_config(1);
9135        activate_all_features(&mut genesis_config);
9136
9137        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9138        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
9139
9140        bank = Arc::new(new_from_parent(&bank));
9141        assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 32)]);
9142        for _ in 2..15 {
9143            bank = Arc::new(new_from_parent(&bank));
9144        }
9145        assert_eq!(bank.rent_collection_partitions(), vec![(13, 14, 32)]);
9146        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 49));
9147        assert_eq!(
9148            bank.rent_collection_partitions(),
9149            vec![(14, 31, 32), (0, 0, 64), (0, 17, 64)]
9150        );
9151        bank = Arc::new(new_from_parent(&bank));
9152        assert_eq!(bank.rent_collection_partitions(), vec![(17, 18, 64)]);
9153    }
9154
9155    #[test]
9156    fn test_rent_eager_across_epoch_with_half_gap() {
9157        let (mut genesis_config, _mint_keypair) = create_genesis_config(1);
9158        activate_all_features(&mut genesis_config);
9159
9160        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9161        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
9162
9163        bank = Arc::new(new_from_parent(&bank));
9164        assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 32)]);
9165        for _ in 2..15 {
9166            bank = Arc::new(new_from_parent(&bank));
9167        }
9168        assert_eq!(bank.rent_collection_partitions(), vec![(13, 14, 32)]);
9169        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 32));
9170        assert_eq!(
9171            bank.rent_collection_partitions(),
9172            vec![(14, 31, 32), (0, 0, 64)]
9173        );
9174        bank = Arc::new(new_from_parent(&bank));
9175        assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 64)]);
9176    }
9177
9178    #[test]
9179    #[allow(clippy::cognitive_complexity)]
9180    fn test_rent_eager_across_epoch_without_gap_under_multi_epoch_cycle() {
9181        let leader_pubkey = solana_sdk::pubkey::new_rand();
9182        let leader_lamports = 3;
9183        let mut genesis_config =
9184            create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
9185        genesis_config.cluster_type = ClusterType::MainnetBeta;
9186
9187        const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64;
9188        const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
9189        genesis_config.epoch_schedule =
9190            EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, false);
9191
9192        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9193        assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000);
9194        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9195        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 0));
9196        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9197
9198        bank = Arc::new(new_from_parent(&bank));
9199        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9200        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 1));
9201        assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 432_000)]);
9202
9203        for _ in 2..32 {
9204            bank = Arc::new(new_from_parent(&bank));
9205        }
9206        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9207        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 31));
9208        assert_eq!(bank.rent_collection_partitions(), vec![(30, 31, 432_000)]);
9209
9210        bank = Arc::new(new_from_parent(&bank));
9211        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9212        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1, 0));
9213        assert_eq!(bank.rent_collection_partitions(), vec![(31, 32, 432_000)]);
9214
9215        bank = Arc::new(new_from_parent(&bank));
9216        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9217        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1, 1));
9218        assert_eq!(bank.rent_collection_partitions(), vec![(32, 33, 432_000)]);
9219
9220        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 1000));
9221        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 1001));
9222        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9223        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (31, 9));
9224        assert_eq!(
9225            bank.rent_collection_partitions(),
9226            vec![(1000, 1001, 432_000)]
9227        );
9228
9229        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 431_998));
9230        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 431_999));
9231        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9232        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (13499, 31));
9233        assert_eq!(
9234            bank.rent_collection_partitions(),
9235            vec![(431_998, 431_999, 432_000)]
9236        );
9237
9238        bank = Arc::new(new_from_parent(&bank));
9239        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9240        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (13500, 0));
9241        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9242
9243        bank = Arc::new(new_from_parent(&bank));
9244        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9245        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (13500, 1));
9246        assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 432_000)]);
9247    }
9248
9249    #[test]
9250    fn test_rent_eager_across_epoch_with_gap_under_multi_epoch_cycle() {
9251        let leader_pubkey = solana_sdk::pubkey::new_rand();
9252        let leader_lamports = 3;
9253        let mut genesis_config =
9254            create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
9255        genesis_config.cluster_type = ClusterType::MainnetBeta;
9256
9257        const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64;
9258        const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
9259        genesis_config.epoch_schedule =
9260            EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, false);
9261
9262        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9263        assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000);
9264        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9265        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 0));
9266        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9267
9268        bank = Arc::new(new_from_parent(&bank));
9269        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9270        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 1));
9271        assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 432_000)]);
9272
9273        for _ in 2..19 {
9274            bank = Arc::new(new_from_parent(&bank));
9275        }
9276        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9277        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 18));
9278        assert_eq!(bank.rent_collection_partitions(), vec![(17, 18, 432_000)]);
9279
9280        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 44));
9281        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9282        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1, 12));
9283        assert_eq!(
9284            bank.rent_collection_partitions(),
9285            vec![(18, 31, 432_000), (31, 31, 432_000), (31, 44, 432_000)]
9286        );
9287
9288        bank = Arc::new(new_from_parent(&bank));
9289        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9290        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1, 13));
9291        assert_eq!(bank.rent_collection_partitions(), vec![(44, 45, 432_000)]);
9292
9293        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 431_993));
9294        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 432_011));
9295        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9296        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (13500, 11));
9297        assert_eq!(
9298            bank.rent_collection_partitions(),
9299            vec![
9300                (431_993, 431_999, 432_000),
9301                (0, 0, 432_000),
9302                (0, 11, 432_000)
9303            ]
9304        );
9305    }
9306
9307    #[test]
9308    fn test_rent_eager_with_warmup_epochs_under_multi_epoch_cycle() {
9309        let leader_pubkey = solana_sdk::pubkey::new_rand();
9310        let leader_lamports = 3;
9311        let mut genesis_config =
9312            create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
9313        genesis_config.cluster_type = ClusterType::MainnetBeta;
9314
9315        const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64 * 8;
9316        const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
9317        genesis_config.epoch_schedule =
9318            EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, true);
9319
9320        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9321        assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000);
9322        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9323        assert_eq!(bank.first_normal_epoch(), 3);
9324        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 0));
9325        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
9326
9327        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 222));
9328        bank = Arc::new(new_from_parent(&bank));
9329        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 128);
9330        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (2, 127));
9331        assert_eq!(bank.rent_collection_partitions(), vec![(126, 127, 128)]);
9332
9333        bank = Arc::new(new_from_parent(&bank));
9334        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9335        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (3, 0));
9336        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 431_872)]);
9337        assert_eq!(431_872 % bank.get_slots_in_epoch(bank.epoch()), 0);
9338
9339        bank = Arc::new(new_from_parent(&bank));
9340        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9341        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (3, 1));
9342        assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 431_872)]);
9343
9344        bank = Arc::new(Bank::new_from_parent(
9345            &bank,
9346            &Pubkey::default(),
9347            431_872 + 223 - 1,
9348        ));
9349        bank = Arc::new(new_from_parent(&bank));
9350        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9351        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1689, 255));
9352        assert_eq!(
9353            bank.rent_collection_partitions(),
9354            vec![(431_870, 431_871, 431_872)]
9355        );
9356
9357        bank = Arc::new(new_from_parent(&bank));
9358        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9359        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (1690, 0));
9360        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 431_872)]);
9361    }
9362
9363    #[test]
9364    fn test_rent_eager_under_fixed_cycle_for_development() {
9365        solana_logger::setup();
9366        let leader_pubkey = solana_sdk::pubkey::new_rand();
9367        let leader_lamports = 3;
9368        let mut genesis_config =
9369            create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
9370
9371        const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64 * 8;
9372        const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
9373        genesis_config.epoch_schedule =
9374            EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, true);
9375
9376        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9377        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 32);
9378        assert_eq!(bank.first_normal_epoch(), 3);
9379        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (0, 0));
9380        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9381
9382        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 222));
9383        bank = Arc::new(new_from_parent(&bank));
9384        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 128);
9385        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (2, 127));
9386        assert_eq!(bank.rent_collection_partitions(), vec![(222, 223, 432_000)]);
9387
9388        bank = Arc::new(new_from_parent(&bank));
9389        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9390        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (3, 0));
9391        assert_eq!(bank.rent_collection_partitions(), vec![(223, 224, 432_000)]);
9392
9393        bank = Arc::new(new_from_parent(&bank));
9394        assert_eq!(bank.get_slots_in_epoch(bank.epoch()), 256);
9395        assert_eq!(bank.get_epoch_and_slot_index(bank.slot()), (3, 1));
9396        assert_eq!(bank.rent_collection_partitions(), vec![(224, 225, 432_000)]);
9397
9398        bank = Arc::new(Bank::new_from_parent(
9399            &bank,
9400            &Pubkey::default(),
9401            432_000 - 2,
9402        ));
9403        bank = Arc::new(new_from_parent(&bank));
9404        assert_eq!(
9405            bank.rent_collection_partitions(),
9406            vec![(431_998, 431_999, 432_000)]
9407        );
9408        bank = Arc::new(new_from_parent(&bank));
9409        assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 432_000)]);
9410        bank = Arc::new(new_from_parent(&bank));
9411        assert_eq!(bank.rent_collection_partitions(), vec![(0, 1, 432_000)]);
9412
9413        bank = Arc::new(Bank::new_from_parent(
9414            &bank,
9415            &Pubkey::default(),
9416            864_000 - 20,
9417        ));
9418        bank = Arc::new(Bank::new_from_parent(
9419            &bank,
9420            &Pubkey::default(),
9421            864_000 + 39,
9422        ));
9423        assert_eq!(
9424            bank.rent_collection_partitions(),
9425            vec![
9426                (431_980, 431_999, 432_000),
9427                (0, 0, 432_000),
9428                (0, 39, 432_000)
9429            ]
9430        );
9431    }
9432
9433    #[test]
9434    fn test_rent_eager_pubkey_range_minimal() {
9435        let range = Bank::pubkey_range_from_partition((0, 0, 1));
9436        assert_eq!(
9437            range,
9438            Pubkey::new_from_array([0x00; 32])..=Pubkey::new_from_array([0xff; 32])
9439        );
9440    }
9441
9442    #[test]
9443    fn test_rent_eager_pubkey_range_maximum() {
9444        let max = !0;
9445
9446        let range = Bank::pubkey_range_from_partition((0, 0, max));
9447        assert_eq!(
9448            range,
9449            Pubkey::new_from_array([0x00; 32])
9450                ..=Pubkey::new_from_array([
9451                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
9452                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9453                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9454                ])
9455        );
9456        let range = Bank::pubkey_range_from_partition((0, 1, max));
9457        const ONE: u8 = 0x01;
9458        assert_eq!(
9459            range,
9460            Pubkey::new_from_array([
9461                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ONE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9462                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9463                0x00, 0x00, 0x00, 0x00,
9464            ])
9465                ..=Pubkey::new_from_array([
9466                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
9467                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9468                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9469                ])
9470        );
9471        let range = Bank::pubkey_range_from_partition((max - 3, max - 2, max));
9472        const FD: u8 = 0xfd;
9473        assert_eq!(
9474            range,
9475            Pubkey::new_from_array([
9476                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9477                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9478                0x00, 0x00, 0x00, 0x00,
9479            ])
9480                ..=Pubkey::new_from_array([
9481                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, FD, 0xff, 0xff, 0xff, 0xff, 0xff,
9482                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9483                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9484                ])
9485        );
9486        let range = Bank::pubkey_range_from_partition((max - 2, max - 1, max));
9487        assert_eq!(
9488            range,
9489            Pubkey::new_from_array([
9490                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9491                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9492                0x00, 0x00, 0x00, 0x00,
9493            ])..=pubkey_max_value()
9494        );
9495
9496        fn should_cause_overflow(partition_count: u64) -> bool {
9497            // Check `partition_width = (u64::max_value() + 1) / partition_count` is exact and
9498            // does not have a remainder.
9499            // This way, `partition_width * partition_count == (u64::max_value() + 1)`,
9500            // so the test actually tests for overflow
9501            (u64::max_value() - partition_count + 1) % partition_count == 0
9502        }
9503
9504        let max_exact = 64;
9505        // Make sure `max_exact` divides evenly when calculating `calculate_partition_width`
9506        assert!(should_cause_overflow(max_exact));
9507        // Make sure `max_inexact` doesn't divide evenly when calculating `calculate_partition_width`
9508        let max_inexact = 10;
9509        assert!(!should_cause_overflow(max_inexact));
9510
9511        for max in &[max_exact, max_inexact] {
9512            let range = Bank::pubkey_range_from_partition((max - 1, max - 1, *max));
9513            assert_eq!(range, pubkey_max_value()..=pubkey_max_value());
9514        }
9515    }
9516
9517    fn map_to_test_bad_range() -> std::collections::BTreeMap<Pubkey, i8> {
9518        let mut map = std::collections::BTreeMap::new();
9519        // when empty, std::collections::BTreeMap doesn't sanitize given range...
9520        map.insert(solana_sdk::pubkey::new_rand(), 1);
9521        map
9522    }
9523
9524    #[test]
9525    #[should_panic(expected = "range start is greater than range end in BTreeMap")]
9526    fn test_rent_eager_bad_range() {
9527        let test_map = map_to_test_bad_range();
9528        let _ = test_map.range(
9529            Pubkey::new_from_array([
9530                0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9531                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9532                0x00, 0x00, 0x00, 0x01,
9533            ])
9534                ..=Pubkey::new_from_array([
9535                    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
9536                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9537                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9538                ]),
9539        );
9540    }
9541
9542    #[test]
9543    fn test_rent_eager_pubkey_range_noop_range() {
9544        let test_map = map_to_test_bad_range();
9545
9546        let range = Bank::pubkey_range_from_partition((0, 0, 3));
9547        assert_eq!(
9548            range,
9549            Pubkey::new_from_array([0x00; 32])
9550                ..=Pubkey::new_from_array([
9551                    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0xff, 0xff, 0xff, 0xff, 0xff,
9552                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9553                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9554                ])
9555        );
9556        let _ = test_map.range(range);
9557
9558        let range = Bank::pubkey_range_from_partition((1, 1, 3));
9559        let same = Pubkey::new_from_array([
9560            0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9561            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9562            0x00, 0x00, 0x00, 0x00,
9563        ]);
9564        assert_eq!(range, same..=same);
9565        let _ = test_map.range(range);
9566
9567        let range = Bank::pubkey_range_from_partition((2, 2, 3));
9568        assert_eq!(range, pubkey_max_value()..=pubkey_max_value());
9569        let _ = test_map.range(range);
9570    }
9571
9572    fn pubkey_max_value() -> Pubkey {
9573        let highest = Pubkey::from_str("JEKNVnkbo3jma5nREBBJCDoXFVeKkD56V3xKrvRmWxFG").unwrap();
9574        let arr = Pubkey::new_from_array([0xff; 32]);
9575        assert_eq!(highest, arr);
9576        arr
9577    }
9578
9579    #[test]
9580    fn test_rent_pubkey_range_max() {
9581        // start==end && start != 0 is curious behavior. Verifying it here.
9582        solana_logger::setup();
9583        let range = Bank::pubkey_range_from_partition((1, 1, 3));
9584        let p = Bank::partition_from_pubkey(range.start(), 3);
9585        assert_eq!(p, 2);
9586        let range = Bank::pubkey_range_from_partition((1, 2, 3));
9587        let p = Bank::partition_from_pubkey(range.start(), 3);
9588        assert_eq!(p, 2);
9589        let range = Bank::pubkey_range_from_partition((2, 2, 3));
9590        let p = Bank::partition_from_pubkey(range.start(), 3);
9591        assert_eq!(p, 2);
9592        let range = Bank::pubkey_range_from_partition((1, 1, 16));
9593        let p = Bank::partition_from_pubkey(range.start(), 16);
9594        assert_eq!(p, 2);
9595        let range = Bank::pubkey_range_from_partition((1, 2, 16));
9596        let p = Bank::partition_from_pubkey(range.start(), 16);
9597        assert_eq!(p, 2);
9598        let range = Bank::pubkey_range_from_partition((2, 2, 16));
9599        let p = Bank::partition_from_pubkey(range.start(), 16);
9600        assert_eq!(p, 3);
9601        let range = Bank::pubkey_range_from_partition((15, 15, 16));
9602        let p = Bank::partition_from_pubkey(range.start(), 16);
9603        assert_eq!(p, 15);
9604    }
9605
9606    #[test]
9607    fn test_rent_eager_pubkey_range_dividable() {
9608        let test_map = map_to_test_bad_range();
9609        let range = Bank::pubkey_range_from_partition((0, 0, 2));
9610
9611        assert_eq!(
9612            range,
9613            Pubkey::new_from_array([0x00; 32])
9614                ..=Pubkey::new_from_array([
9615                    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9616                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9617                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9618                ])
9619        );
9620        let _ = test_map.range(range);
9621
9622        let range = Bank::pubkey_range_from_partition((0, 1, 2));
9623        assert_eq!(
9624            range,
9625            Pubkey::new_from_array([
9626                0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9627                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9628                0x00, 0x00, 0x00, 0x00
9629            ])
9630                ..=Pubkey::new_from_array([
9631                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9632                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9633                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9634                ])
9635        );
9636        let _ = test_map.range(range);
9637    }
9638
9639    #[test]
9640    fn test_rent_eager_pubkey_range_not_dividable() {
9641        solana_logger::setup();
9642
9643        let test_map = map_to_test_bad_range();
9644        let range = Bank::pubkey_range_from_partition((0, 0, 3));
9645        assert_eq!(
9646            range,
9647            Pubkey::new_from_array([0x00; 32])
9648                ..=Pubkey::new_from_array([
9649                    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0xff, 0xff, 0xff, 0xff, 0xff,
9650                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9651                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9652                ])
9653        );
9654        let _ = test_map.range(range);
9655
9656        let range = Bank::pubkey_range_from_partition((0, 1, 3));
9657        assert_eq!(
9658            range,
9659            Pubkey::new_from_array([
9660                0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9661                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9662                0x00, 0x00, 0x00, 0x00
9663            ])
9664                ..=Pubkey::new_from_array([
9665                    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa9, 0xff, 0xff, 0xff, 0xff, 0xff,
9666                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9667                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9668                ])
9669        );
9670        let _ = test_map.range(range);
9671
9672        let range = Bank::pubkey_range_from_partition((1, 2, 3));
9673        assert_eq!(
9674            range,
9675            Pubkey::new_from_array([
9676                0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9677                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9678                0x00, 0x00, 0x00, 0x00
9679            ])
9680                ..=Pubkey::new_from_array([
9681                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9682                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9683                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9684                ])
9685        );
9686        let _ = test_map.range(range);
9687    }
9688
9689    #[test]
9690    fn test_rent_eager_pubkey_range_gap() {
9691        solana_logger::setup();
9692
9693        let test_map = map_to_test_bad_range();
9694        let range = Bank::pubkey_range_from_partition((120, 1023, 12345));
9695        assert_eq!(
9696            range,
9697            Pubkey::new_from_array([
9698                0x02, 0x82, 0x5a, 0x89, 0xd1, 0xac, 0x58, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9699                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9700                0x00, 0x00, 0x00, 0x00
9701            ])
9702                ..=Pubkey::new_from_array([
9703                    0x15, 0x3c, 0x1d, 0xf1, 0xc6, 0x39, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9704                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
9705                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff
9706                ])
9707        );
9708        let _ = test_map.range(range);
9709    }
9710
9711    impl Bank {
9712        fn slots_by_pubkey(&self, pubkey: &Pubkey, ancestors: &Ancestors) -> Vec<Slot> {
9713            let (locked_entry, _) = self
9714                .rc
9715                .accounts
9716                .accounts_db
9717                .accounts_index
9718                .get(pubkey, Some(ancestors), None)
9719                .unwrap();
9720            locked_entry
9721                .slot_list()
9722                .iter()
9723                .map(|(slot, _)| *slot)
9724                .collect::<Vec<Slot>>()
9725        }
9726    }
9727
9728    #[test]
9729    fn test_rent_eager_collect_rent_in_partition() {
9730        solana_logger::setup();
9731
9732        let (mut genesis_config, _mint_keypair) = create_genesis_config(1_000_000);
9733        activate_all_features(&mut genesis_config);
9734
9735        let zero_lamport_pubkey = solana_sdk::pubkey::new_rand();
9736        let rent_due_pubkey = solana_sdk::pubkey::new_rand();
9737        let rent_exempt_pubkey = solana_sdk::pubkey::new_rand();
9738
9739        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
9740        let zero_lamports = 0;
9741        let little_lamports = 1234;
9742        let large_lamports = 123_456_789;
9743        // genesis_config.epoch_schedule.slots_per_epoch == 432_000 and is unsuitable for this test
9744        let some_slot = MINIMUM_SLOTS_PER_EPOCH; // chosen to cause epoch to be +1
9745        let rent_collected = 1; // this is a function of 'some_slot'
9746
9747        bank.store_account(
9748            &zero_lamport_pubkey,
9749            &AccountSharedData::new(zero_lamports, 0, &Pubkey::default()),
9750        );
9751        bank.store_account(
9752            &rent_due_pubkey,
9753            &AccountSharedData::new(little_lamports, 0, &Pubkey::default()),
9754        );
9755        bank.store_account(
9756            &rent_exempt_pubkey,
9757            &AccountSharedData::new(large_lamports, 0, &Pubkey::default()),
9758        );
9759
9760        let genesis_slot = 0;
9761        let ancestors = vec![(some_slot, 0), (0, 1)].into_iter().collect();
9762
9763        let previous_epoch = bank.epoch();
9764        bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), some_slot));
9765        let current_epoch = bank.epoch();
9766        assert_eq!(previous_epoch + 1, current_epoch);
9767
9768        assert_eq!(bank.collected_rent.load(Relaxed), 0);
9769        assert_eq!(
9770            bank.get_account(&rent_due_pubkey).unwrap().lamports(),
9771            little_lamports
9772        );
9773        assert_eq!(bank.get_account(&rent_due_pubkey).unwrap().rent_epoch(), 0);
9774        assert_eq!(
9775            bank.slots_by_pubkey(&rent_due_pubkey, &ancestors),
9776            vec![genesis_slot]
9777        );
9778        assert_eq!(
9779            bank.slots_by_pubkey(&rent_exempt_pubkey, &ancestors),
9780            vec![genesis_slot]
9781        );
9782        assert_eq!(
9783            bank.slots_by_pubkey(&zero_lamport_pubkey, &ancestors),
9784            vec![genesis_slot]
9785        );
9786
9787        assert_eq!(bank.collected_rent.load(Relaxed), 0);
9788        assert!(bank.rewrites_skipped_this_slot.read().unwrap().is_empty());
9789        bank.collect_rent_in_partition((0, 0, 1), true, &RentMetrics::default());
9790        {
9791            let rewrites_skipped = bank.rewrites_skipped_this_slot.read().unwrap();
9792            // `rewrites_skipped.len()` is the number of non-rent paying accounts in the slot.
9793            // 'collect_rent_in_partition' fills 'rewrites_skipped_this_slot' with rewrites that
9794            // were skipped during rent collection but should still be considered in the slot's
9795            // bank hash. If the slot is also written in the append vec, then the bank hash calc
9796            // code ignores the contents of this list. This assert is confirming that the expected #
9797            // of accounts were included in 'rewrites_skipped' by the call to
9798            // 'collect_rent_in_partition(..., true)' above.
9799            assert_eq!(rewrites_skipped.len(), 1);
9800            // should not have skipped 'rent_exempt_pubkey'
9801            // Once preserve_rent_epoch_for_rent_exempt_accounts is activated,
9802            // rewrite-skip is irrelevant to rent-exempt accounts.
9803            assert!(!rewrites_skipped.contains_key(&rent_exempt_pubkey));
9804            // should NOT have skipped 'rent_due_pubkey'
9805            assert!(!rewrites_skipped.contains_key(&rent_due_pubkey));
9806        }
9807
9808        assert_eq!(bank.collected_rent.load(Relaxed), 0);
9809        bank.collect_rent_in_partition((0, 0, 1), false, &RentMetrics::default()); // all range
9810
9811        assert_eq!(bank.collected_rent.load(Relaxed), rent_collected);
9812        assert_eq!(
9813            bank.get_account(&rent_due_pubkey).unwrap().lamports(),
9814            little_lamports - rent_collected
9815        );
9816        assert_eq!(
9817            bank.get_account(&rent_due_pubkey).unwrap().rent_epoch(),
9818            current_epoch + 1
9819        );
9820        assert_eq!(
9821            bank.get_account(&rent_exempt_pubkey).unwrap().lamports(),
9822            large_lamports
9823        );
9824        // Once preserve_rent_epoch_for_rent_exempt_accounts is activated,
9825        // rent_epoch of rent-exempt accounts will no longer advance.
9826        assert_eq!(
9827            bank.get_account(&rent_exempt_pubkey).unwrap().rent_epoch(),
9828            0
9829        );
9830        assert_eq!(
9831            bank.slots_by_pubkey(&rent_due_pubkey, &ancestors),
9832            vec![genesis_slot, some_slot]
9833        );
9834        assert_eq!(
9835            bank.slots_by_pubkey(&rent_exempt_pubkey, &ancestors),
9836            vec![genesis_slot, some_slot]
9837        );
9838        assert_eq!(
9839            bank.slots_by_pubkey(&zero_lamport_pubkey, &ancestors),
9840            vec![genesis_slot]
9841        );
9842    }
9843
9844    fn new_from_parent_next_epoch(parent: &Arc<Bank>, epochs: Epoch) -> Bank {
9845        let mut slot = parent.slot();
9846        let mut epoch = parent.epoch();
9847        for _ in 0..epochs {
9848            slot += parent.epoch_schedule().get_slots_in_epoch(epoch);
9849            epoch = parent.epoch_schedule().get_epoch(slot);
9850        }
9851
9852        Bank::new_from_parent(parent, &Pubkey::default(), slot)
9853    }
9854
9855    #[test]
9856    /// tests that an account which has already had rent collected IN this slot does not skip rewrites
9857    fn test_collect_rent_from_accounts() {
9858        solana_logger::setup();
9859
9860        let zero_lamport_pubkey = Pubkey::from([0; 32]);
9861
9862        let genesis_bank = create_simple_test_arc_bank(100000);
9863        let first_bank = Arc::new(new_from_parent(&genesis_bank));
9864        let first_slot = 1;
9865        assert_eq!(first_slot, first_bank.slot());
9866        let epoch_delta = 4;
9867        let later_bank = Arc::new(new_from_parent_next_epoch(&first_bank, epoch_delta)); // a bank a few epochs in the future
9868        let later_slot = later_bank.slot();
9869        assert!(later_bank.epoch() == genesis_bank.epoch() + epoch_delta);
9870
9871        let data_size = 0; // make sure we're rent exempt
9872        let lamports = later_bank.get_minimum_balance_for_rent_exemption(data_size); // cannot be 0 or we zero out rent_epoch in rent collection and we need to be rent exempt
9873        let mut account = AccountSharedData::new(lamports, data_size, &Pubkey::default());
9874        account.set_rent_epoch(later_bank.epoch() - 1); // non-zero, but less than later_bank's epoch
9875
9876        let just_rewrites = true;
9877        // 'later_slot' here is the slot the account was loaded from.
9878        // Since 'later_slot' is the same slot the bank is in, this means that the account was already written IN this slot.
9879        // So, we should NOT skip rewrites.
9880        let result = later_bank.collect_rent_from_accounts(
9881            vec![(zero_lamport_pubkey, account.clone(), later_slot)],
9882            just_rewrites,
9883            None,
9884            PartitionIndex::default(),
9885        );
9886        assert!(result.rewrites_skipped.is_empty());
9887        // loaded from previous slot, so we skip rent collection on it
9888        let result = later_bank.collect_rent_from_accounts(
9889            vec![(zero_lamport_pubkey, account, later_slot - 1)],
9890            just_rewrites,
9891            None,
9892            PartitionIndex::default(),
9893        );
9894        assert!(result.rewrites_skipped[0].0 == zero_lamport_pubkey);
9895    }
9896
9897    #[test]
9898    fn test_rent_eager_collect_rent_zero_lamport_deterministic() {
9899        solana_logger::setup();
9900
9901        let (genesis_config, _mint_keypair) = create_genesis_config(1);
9902
9903        let zero_lamport_pubkey = solana_sdk::pubkey::new_rand();
9904
9905        let genesis_bank1 = Arc::new(Bank::new_for_tests(&genesis_config));
9906        let genesis_bank2 = Arc::new(Bank::new_for_tests(&genesis_config));
9907        let bank1_with_zero = Arc::new(new_from_parent(&genesis_bank1));
9908        let bank1_without_zero = Arc::new(new_from_parent(&genesis_bank2));
9909
9910        let zero_lamports = 0;
9911        let data_size = 12345; // use non-zero data size to also test accounts_data_size
9912        let account = AccountSharedData::new(zero_lamports, data_size, &Pubkey::default());
9913        bank1_with_zero.store_account(&zero_lamport_pubkey, &account);
9914        bank1_without_zero.store_account(&zero_lamport_pubkey, &account);
9915
9916        bank1_without_zero
9917            .rc
9918            .accounts
9919            .accounts_db
9920            .accounts_index
9921            .add_root(genesis_bank1.slot() + 1, false);
9922        bank1_without_zero
9923            .rc
9924            .accounts
9925            .accounts_db
9926            .accounts_index
9927            .purge_roots(&zero_lamport_pubkey);
9928
9929        // genesis_config.epoch_schedule.slots_per_epoch == 432_000 and is unsuitable for this test
9930        let some_slot = MINIMUM_SLOTS_PER_EPOCH; // 1 epoch
9931        let bank2_with_zero = Arc::new(Bank::new_from_parent(
9932            &bank1_with_zero,
9933            &Pubkey::default(),
9934            some_slot,
9935        ));
9936        assert_eq!(bank1_with_zero.epoch() + 1, bank2_with_zero.epoch());
9937        let bank2_without_zero = Arc::new(Bank::new_from_parent(
9938            &bank1_without_zero,
9939            &Pubkey::default(),
9940            some_slot,
9941        ));
9942        let hash1_with_zero = bank1_with_zero.hash();
9943        let hash1_without_zero = bank1_without_zero.hash();
9944        assert_eq!(hash1_with_zero, hash1_without_zero);
9945        assert_ne!(hash1_with_zero, Hash::default());
9946
9947        bank2_with_zero.collect_rent_in_partition((0, 0, 1), false, &RentMetrics::default()); // all
9948        bank2_without_zero.collect_rent_in_partition((0, 0, 1), false, &RentMetrics::default()); // all
9949
9950        bank2_with_zero.freeze();
9951        let hash2_with_zero = bank2_with_zero.hash();
9952        bank2_without_zero.freeze();
9953        let hash2_without_zero = bank2_without_zero.hash();
9954
9955        assert_eq!(hash2_with_zero, hash2_without_zero);
9956        assert_ne!(hash2_with_zero, Hash::default());
9957    }
9958
9959    #[test]
9960    fn test_bank_update_vote_stake_rewards() {
9961        let thread_pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();
9962        check_bank_update_vote_stake_rewards(|bank: &Bank| {
9963            bank.load_vote_and_stake_accounts_with_thread_pool(&thread_pool, null_tracer())
9964        });
9965        check_bank_update_vote_stake_rewards(|bank: &Bank| {
9966            bank.load_vote_and_stake_accounts(&thread_pool, null_tracer())
9967        });
9968    }
9969
9970    fn check_bank_update_vote_stake_rewards<F>(load_vote_and_stake_accounts: F)
9971    where
9972        F: Fn(&Bank) -> LoadVoteAndStakeAccountsResult,
9973    {
9974        solana_logger::setup();
9975
9976        // create a bank that ticks really slowly...
9977        let bank0 = Arc::new(Bank::new_for_tests(&GenesisConfig {
9978            accounts: (0..42)
9979                .map(|_| {
9980                    (
9981                        solana_sdk::pubkey::new_rand(),
9982                        Account::new(1_000_000_000, 0, &Pubkey::default()),
9983                    )
9984                })
9985                .collect(),
9986            // set it up so the first epoch is a full year long
9987            poh_config: PohConfig {
9988                target_tick_duration: Duration::from_secs(
9989                    SECONDS_PER_YEAR as u64
9990                        / MINIMUM_SLOTS_PER_EPOCH as u64
9991                        / DEFAULT_TICKS_PER_SLOT,
9992                ),
9993                hashes_per_tick: None,
9994                target_tick_count: None,
9995            },
9996            cluster_type: ClusterType::MainnetBeta,
9997
9998            ..GenesisConfig::default()
9999        }));
10000
10001        // enable lazy rent collection because this test depends on rent-due accounts
10002        // not being eagerly-collected for exact rewards calculation
10003        bank0.restore_old_behavior_for_fragile_tests();
10004
10005        assert_eq!(
10006            bank0.capitalization(),
10007            42 * 1_000_000_000 + genesis_sysvar_and_builtin_program_lamports(),
10008        );
10009
10010        let ((vote_id, mut vote_account), (stake_id, stake_account)) =
10011            crate::stakes::tests::create_staked_node_accounts(10_000);
10012        let starting_vote_and_stake_balance = 10_000 + 1;
10013
10014        // set up accounts
10015        bank0.store_account_and_update_capitalization(&stake_id, &stake_account);
10016
10017        // generate some rewards
10018        let mut vote_state = Some(VoteState::from(&vote_account).unwrap());
10019        for i in 0..MAX_LOCKOUT_HISTORY + 42 {
10020            if let Some(v) = vote_state.as_mut() {
10021                v.process_slot_vote_unchecked(i as u64)
10022            }
10023            let versioned = VoteStateVersions::Current(Box::new(vote_state.take().unwrap()));
10024            VoteState::to(&versioned, &mut vote_account).unwrap();
10025            bank0.store_account_and_update_capitalization(&vote_id, &vote_account);
10026            match versioned {
10027                VoteStateVersions::Current(v) => {
10028                    vote_state = Some(*v);
10029                }
10030                _ => panic!("Has to be of type Current"),
10031            };
10032        }
10033        bank0.store_account_and_update_capitalization(&vote_id, &vote_account);
10034        bank0.freeze();
10035
10036        assert_eq!(
10037            bank0.capitalization(),
10038            42 * 1_000_000_000
10039                + genesis_sysvar_and_builtin_program_lamports()
10040                + starting_vote_and_stake_balance
10041                + bank0_sysvar_delta(),
10042        );
10043        assert!(bank0.rewards.read().unwrap().is_empty());
10044
10045        load_vote_and_stake_accounts(&bank0);
10046
10047        // put a child bank in epoch 1, which calls update_rewards()...
10048        let bank1 = Bank::new_from_parent(
10049            &bank0,
10050            &Pubkey::default(),
10051            bank0.get_slots_in_epoch(bank0.epoch()) + 1,
10052        );
10053        // verify that there's inflation
10054        assert_ne!(bank1.capitalization(), bank0.capitalization());
10055
10056        // verify the inflation is represented in validator_points
10057        let paid_rewards = bank1.capitalization() - bank0.capitalization() - bank1_sysvar_delta();
10058
10059        // this assumes that no new builtins or precompiles were activated in bank1
10060        let PrevEpochInflationRewards {
10061            validator_rewards, ..
10062        } = bank1.calculate_previous_epoch_inflation_rewards(bank0.capitalization(), bank0.epoch());
10063
10064        // verify the stake and vote accounts are the right size
10065        assert!(
10066            ((bank1.get_balance(&stake_id) - stake_account.lamports() + bank1.get_balance(&vote_id)
10067                - vote_account.lamports()) as f64
10068                - validator_rewards as f64)
10069                .abs()
10070                < 1.0
10071        );
10072
10073        // verify the rewards are the right size
10074        assert!((validator_rewards as f64 - paid_rewards as f64).abs() < 1.0); // rounding, truncating
10075
10076        // verify validator rewards show up in bank1.rewards vector
10077        assert_eq!(
10078            *bank1.rewards.read().unwrap(),
10079            vec![
10080                (
10081                    vote_id,
10082                    RewardInfo {
10083                        reward_type: RewardType::Voting,
10084                        lamports: 0,
10085                        post_balance: bank1.get_balance(&vote_id),
10086                        commission: Some(0),
10087                    }
10088                ),
10089                (
10090                    stake_id,
10091                    RewardInfo {
10092                        reward_type: RewardType::Staking,
10093                        lamports: validator_rewards as i64,
10094                        post_balance: bank1.get_balance(&stake_id),
10095                        commission: Some(0),
10096                    }
10097                )
10098            ]
10099        );
10100        bank1.freeze();
10101        assert!(bank1.calculate_and_verify_capitalization(true));
10102    }
10103
10104    fn do_test_bank_update_rewards_determinism() -> u64 {
10105        // create a bank that ticks really slowly...
10106        let bank = Arc::new(Bank::new_for_tests(&GenesisConfig {
10107            accounts: (0..42)
10108                .map(|_| {
10109                    (
10110                        solana_sdk::pubkey::new_rand(),
10111                        Account::new(1_000_000_000, 0, &Pubkey::default()),
10112                    )
10113                })
10114                .collect(),
10115            // set it up so the first epoch is a full year long
10116            poh_config: PohConfig {
10117                target_tick_duration: Duration::from_secs(
10118                    SECONDS_PER_YEAR as u64
10119                        / MINIMUM_SLOTS_PER_EPOCH as u64
10120                        / DEFAULT_TICKS_PER_SLOT,
10121                ),
10122                hashes_per_tick: None,
10123                target_tick_count: None,
10124            },
10125            cluster_type: ClusterType::MainnetBeta,
10126
10127            ..GenesisConfig::default()
10128        }));
10129
10130        // enable lazy rent collection because this test depends on rent-due accounts
10131        // not being eagerly-collected for exact rewards calculation
10132        bank.restore_old_behavior_for_fragile_tests();
10133
10134        assert_eq!(
10135            bank.capitalization(),
10136            42 * 1_000_000_000 + genesis_sysvar_and_builtin_program_lamports()
10137        );
10138
10139        let vote_id = solana_sdk::pubkey::new_rand();
10140        let mut vote_account =
10141            vote_state::create_account(&vote_id, &solana_sdk::pubkey::new_rand(), 0, 100);
10142        let (stake_id1, stake_account1) = crate::stakes::tests::create_stake_account(123, &vote_id);
10143        let (stake_id2, stake_account2) = crate::stakes::tests::create_stake_account(456, &vote_id);
10144
10145        // set up accounts
10146        bank.store_account_and_update_capitalization(&stake_id1, &stake_account1);
10147        bank.store_account_and_update_capitalization(&stake_id2, &stake_account2);
10148
10149        // generate some rewards
10150        let mut vote_state = Some(VoteState::from(&vote_account).unwrap());
10151        for i in 0..MAX_LOCKOUT_HISTORY + 42 {
10152            if let Some(v) = vote_state.as_mut() {
10153                v.process_slot_vote_unchecked(i as u64)
10154            }
10155            let versioned = VoteStateVersions::Current(Box::new(vote_state.take().unwrap()));
10156            VoteState::to(&versioned, &mut vote_account).unwrap();
10157            bank.store_account_and_update_capitalization(&vote_id, &vote_account);
10158            match versioned {
10159                VoteStateVersions::Current(v) => {
10160                    vote_state = Some(*v);
10161                }
10162                _ => panic!("Has to be of type Current"),
10163            };
10164        }
10165        bank.store_account_and_update_capitalization(&vote_id, &vote_account);
10166
10167        // put a child bank in epoch 1, which calls update_rewards()...
10168        let bank1 = Bank::new_from_parent(
10169            &bank,
10170            &Pubkey::default(),
10171            bank.get_slots_in_epoch(bank.epoch()) + 1,
10172        );
10173        // verify that there's inflation
10174        assert_ne!(bank1.capitalization(), bank.capitalization());
10175
10176        bank1.freeze();
10177        assert!(bank1.calculate_and_verify_capitalization(true));
10178
10179        // verify voting and staking rewards are recorded
10180        let rewards = bank1.rewards.read().unwrap();
10181        rewards
10182            .iter()
10183            .find(|(_address, reward)| reward.reward_type == RewardType::Voting)
10184            .unwrap();
10185        rewards
10186            .iter()
10187            .find(|(_address, reward)| reward.reward_type == RewardType::Staking)
10188            .unwrap();
10189
10190        bank1.capitalization()
10191    }
10192
10193    #[test]
10194    fn test_bank_update_rewards_determinism() {
10195        solana_logger::setup();
10196
10197        // The same reward should be distributed given same credits
10198        let expected_capitalization = do_test_bank_update_rewards_determinism();
10199        // Repeat somewhat large number of iterations to expose possible different behavior
10200        // depending on the randomly-seeded HashMap ordering
10201        for _ in 0..30 {
10202            let actual_capitalization = do_test_bank_update_rewards_determinism();
10203            assert_eq!(actual_capitalization, expected_capitalization);
10204        }
10205    }
10206
10207    impl VerifyBankHash {
10208        fn default_for_test() -> Self {
10209            Self {
10210                test_hash_calculation: true,
10211                can_cached_slot_be_unflushed: false,
10212                ignore_mismatch: false,
10213                require_rooted_bank: false,
10214                run_in_background: false,
10215                store_hash_raw_data_for_debug: false,
10216            }
10217        }
10218    }
10219
10220    // Test that purging 0 lamports accounts works.
10221    #[test]
10222    fn test_purge_empty_accounts() {
10223        solana_logger::setup();
10224        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10225        let amount = genesis_config.rent.minimum_balance(0);
10226        let parent = Arc::new(Bank::new_for_tests(&genesis_config));
10227        let mut bank = parent;
10228        for _ in 0..10 {
10229            let blockhash = bank.last_blockhash();
10230            let pubkey = solana_sdk::pubkey::new_rand();
10231            let tx = system_transaction::transfer(&mint_keypair, &pubkey, 0, blockhash);
10232            bank.process_transaction(&tx).unwrap();
10233            bank.freeze();
10234            bank.squash();
10235            bank = Arc::new(new_from_parent(&bank));
10236        }
10237
10238        bank.freeze();
10239        bank.squash();
10240        bank.force_flush_accounts_cache();
10241        let hash = bank.update_accounts_hash();
10242        bank.clean_accounts(false, false, None);
10243        assert_eq!(bank.update_accounts_hash(), hash);
10244
10245        let bank0 = Arc::new(new_from_parent(&bank));
10246        let blockhash = bank.last_blockhash();
10247        let keypair = Keypair::new();
10248        let tx = system_transaction::transfer(&mint_keypair, &keypair.pubkey(), amount, blockhash);
10249        bank0.process_transaction(&tx).unwrap();
10250
10251        let bank1 = Arc::new(new_from_parent(&bank0));
10252        let pubkey = solana_sdk::pubkey::new_rand();
10253        let blockhash = bank.last_blockhash();
10254        let tx = system_transaction::transfer(&keypair, &pubkey, amount, blockhash);
10255        bank1.process_transaction(&tx).unwrap();
10256
10257        assert_eq!(
10258            bank0.get_account(&keypair.pubkey()).unwrap().lamports(),
10259            amount
10260        );
10261        assert_eq!(bank1.get_account(&keypair.pubkey()), None);
10262
10263        info!("bank0 purge");
10264        let hash = bank0.update_accounts_hash();
10265        bank0.clean_accounts(false, false, None);
10266        assert_eq!(bank0.update_accounts_hash(), hash);
10267
10268        assert_eq!(
10269            bank0.get_account(&keypair.pubkey()).unwrap().lamports(),
10270            amount
10271        );
10272        assert_eq!(bank1.get_account(&keypair.pubkey()), None);
10273
10274        info!("bank1 purge");
10275        bank1.clean_accounts(false, false, None);
10276
10277        assert_eq!(
10278            bank0.get_account(&keypair.pubkey()).unwrap().lamports(),
10279            amount
10280        );
10281        assert_eq!(bank1.get_account(&keypair.pubkey()), None);
10282
10283        assert!(bank0.verify_bank_hash(VerifyBankHash::default_for_test()));
10284
10285        // Squash and then verify hash_internal value
10286        bank0.freeze();
10287        bank0.squash();
10288        assert!(bank0.verify_bank_hash(VerifyBankHash::default_for_test()));
10289
10290        bank1.freeze();
10291        bank1.squash();
10292        bank1.update_accounts_hash();
10293        assert!(bank1.verify_bank_hash(VerifyBankHash::default_for_test()));
10294
10295        // keypair should have 0 tokens on both forks
10296        assert_eq!(bank0.get_account(&keypair.pubkey()), None);
10297        assert_eq!(bank1.get_account(&keypair.pubkey()), None);
10298        bank1.force_flush_accounts_cache();
10299        bank1.clean_accounts(false, false, None);
10300
10301        assert!(bank1.verify_bank_hash(VerifyBankHash::default_for_test()));
10302    }
10303
10304    #[test]
10305    fn test_two_payments_to_one_party() {
10306        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10307        let pubkey = solana_sdk::pubkey::new_rand();
10308        let bank = Bank::new_for_tests(&genesis_config);
10309        let amount = genesis_config.rent.minimum_balance(0);
10310        assert_eq!(bank.last_blockhash(), genesis_config.hash());
10311
10312        bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
10313        assert_eq!(bank.get_balance(&pubkey), amount);
10314
10315        bank.transfer(amount * 2, &mint_keypair, &pubkey).unwrap();
10316        assert_eq!(bank.get_balance(&pubkey), amount * 3);
10317        assert_eq!(bank.transaction_count(), 2);
10318    }
10319
10320    #[test]
10321    fn test_one_source_two_tx_one_batch() {
10322        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10323        let key1 = solana_sdk::pubkey::new_rand();
10324        let key2 = solana_sdk::pubkey::new_rand();
10325        let bank = Bank::new_for_tests(&genesis_config);
10326        let amount = genesis_config.rent.minimum_balance(0);
10327        assert_eq!(bank.last_blockhash(), genesis_config.hash());
10328
10329        let t1 = system_transaction::transfer(&mint_keypair, &key1, amount, genesis_config.hash());
10330        let t2 = system_transaction::transfer(&mint_keypair, &key2, amount, genesis_config.hash());
10331        let txs = vec![t1.clone(), t2.clone()];
10332        let res = bank.process_transactions(txs.iter());
10333
10334        assert_eq!(res.len(), 2);
10335        assert_eq!(res[0], Ok(()));
10336        assert_eq!(res[1], Err(TransactionError::AccountInUse));
10337        assert_eq!(
10338            bank.get_balance(&mint_keypair.pubkey()),
10339            sol_to_lamports(1.) - amount
10340        );
10341        assert_eq!(bank.get_balance(&key1), amount);
10342        assert_eq!(bank.get_balance(&key2), 0);
10343        assert_eq!(bank.get_signature_status(&t1.signatures[0]), Some(Ok(())));
10344        // TODO: Transactions that fail to pay a fee could be dropped silently.
10345        // Non-instruction errors don't get logged in the signature cache
10346        assert_eq!(bank.get_signature_status(&t2.signatures[0]), None);
10347    }
10348
10349    #[test]
10350    fn test_one_tx_two_out_atomic_fail() {
10351        let amount = sol_to_lamports(1.);
10352        let (genesis_config, mint_keypair) = create_genesis_config(amount);
10353        let key1 = solana_sdk::pubkey::new_rand();
10354        let key2 = solana_sdk::pubkey::new_rand();
10355        let bank = Bank::new_for_tests(&genesis_config);
10356        let instructions = system_instruction::transfer_many(
10357            &mint_keypair.pubkey(),
10358            &[(key1, amount), (key2, amount)],
10359        );
10360        let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
10361        let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash());
10362        assert_eq!(
10363            bank.process_transaction(&tx).unwrap_err(),
10364            TransactionError::InstructionError(1, SystemError::ResultWithNegativeLamports.into())
10365        );
10366        assert_eq!(bank.get_balance(&mint_keypair.pubkey()), amount);
10367        assert_eq!(bank.get_balance(&key1), 0);
10368        assert_eq!(bank.get_balance(&key2), 0);
10369    }
10370
10371    #[test]
10372    fn test_one_tx_two_out_atomic_pass() {
10373        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10374        let key1 = solana_sdk::pubkey::new_rand();
10375        let key2 = solana_sdk::pubkey::new_rand();
10376        let bank = Bank::new_for_tests(&genesis_config);
10377        let amount = genesis_config.rent.minimum_balance(0);
10378        let instructions = system_instruction::transfer_many(
10379            &mint_keypair.pubkey(),
10380            &[(key1, amount), (key2, amount)],
10381        );
10382        let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
10383        let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash());
10384        bank.process_transaction(&tx).unwrap();
10385        assert_eq!(
10386            bank.get_balance(&mint_keypair.pubkey()),
10387            sol_to_lamports(1.) - (2 * amount)
10388        );
10389        assert_eq!(bank.get_balance(&key1), amount);
10390        assert_eq!(bank.get_balance(&key2), amount);
10391    }
10392
10393    // This test demonstrates that fees are paid even when a program fails.
10394    #[test]
10395    fn test_detect_failed_duplicate_transactions() {
10396        let (mut genesis_config, mint_keypair) = create_genesis_config(10_000);
10397        genesis_config.fee_rate_governor = FeeRateGovernor::new(5_000, 0);
10398        let bank = Bank::new_for_tests(&genesis_config);
10399
10400        let dest = Keypair::new();
10401
10402        // source with 0 program context
10403        let tx = system_transaction::transfer(
10404            &mint_keypair,
10405            &dest.pubkey(),
10406            10_000,
10407            genesis_config.hash(),
10408        );
10409        let signature = tx.signatures[0];
10410        assert!(!bank.has_signature(&signature));
10411
10412        assert_eq!(
10413            bank.process_transaction(&tx),
10414            Err(TransactionError::InstructionError(
10415                0,
10416                SystemError::ResultWithNegativeLamports.into(),
10417            ))
10418        );
10419
10420        // The lamports didn't move, but the from address paid the transaction fee.
10421        assert_eq!(bank.get_balance(&dest.pubkey()), 0);
10422
10423        // This should be the original balance minus the transaction fee.
10424        assert_eq!(bank.get_balance(&mint_keypair.pubkey()), 5000);
10425    }
10426
10427    #[test]
10428    fn test_account_not_found() {
10429        solana_logger::setup();
10430        let (genesis_config, mint_keypair) = create_genesis_config(0);
10431        let bank = Bank::new_for_tests(&genesis_config);
10432        let keypair = Keypair::new();
10433        assert_eq!(
10434            bank.transfer(
10435                genesis_config.rent.minimum_balance(0),
10436                &keypair,
10437                &mint_keypair.pubkey()
10438            ),
10439            Err(TransactionError::AccountNotFound)
10440        );
10441        assert_eq!(bank.transaction_count(), 0);
10442    }
10443
10444    #[test]
10445    fn test_insufficient_funds() {
10446        let mint_amount = sol_to_lamports(1.);
10447        let (genesis_config, mint_keypair) = create_genesis_config(mint_amount);
10448        let bank = Bank::new_for_tests(&genesis_config);
10449        let pubkey = solana_sdk::pubkey::new_rand();
10450        let amount = genesis_config.rent.minimum_balance(0);
10451        bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
10452        assert_eq!(bank.transaction_count(), 1);
10453        assert_eq!(bank.get_balance(&pubkey), amount);
10454        assert_eq!(
10455            bank.transfer((mint_amount - amount) + 1, &mint_keypair, &pubkey),
10456            Err(TransactionError::InstructionError(
10457                0,
10458                SystemError::ResultWithNegativeLamports.into(),
10459            ))
10460        );
10461        assert_eq!(bank.transaction_count(), 1);
10462
10463        let mint_pubkey = mint_keypair.pubkey();
10464        assert_eq!(bank.get_balance(&mint_pubkey), mint_amount - amount);
10465        assert_eq!(bank.get_balance(&pubkey), amount);
10466    }
10467
10468    #[test]
10469    fn test_transfer_to_newb() {
10470        solana_logger::setup();
10471        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10472        let bank = Bank::new_for_tests(&genesis_config);
10473        let amount = genesis_config.rent.minimum_balance(0);
10474        let pubkey = solana_sdk::pubkey::new_rand();
10475        bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
10476        assert_eq!(bank.get_balance(&pubkey), amount);
10477    }
10478
10479    #[test]
10480    fn test_transfer_to_sysvar() {
10481        solana_logger::setup();
10482        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
10483        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
10484        let amount = genesis_config.rent.minimum_balance(0);
10485
10486        let normal_pubkey = solana_sdk::pubkey::new_rand();
10487        let sysvar_pubkey = sysvar::clock::id();
10488        assert_eq!(bank.get_balance(&normal_pubkey), 0);
10489        assert_eq!(bank.get_balance(&sysvar_pubkey), 1_169_280);
10490
10491        bank.transfer(amount, &mint_keypair, &normal_pubkey)
10492            .unwrap();
10493        bank.transfer(amount, &mint_keypair, &sysvar_pubkey)
10494            .unwrap_err();
10495        assert_eq!(bank.get_balance(&normal_pubkey), amount);
10496        assert_eq!(bank.get_balance(&sysvar_pubkey), 1_169_280);
10497
10498        let bank = Arc::new(new_from_parent(&bank));
10499        assert_eq!(bank.get_balance(&normal_pubkey), amount);
10500        assert_eq!(bank.get_balance(&sysvar_pubkey), 1_169_280);
10501    }
10502
10503    #[test]
10504    fn test_bank_deposit() {
10505        let bank = create_simple_test_bank(100);
10506
10507        // Test new account
10508        let key = Keypair::new();
10509        let new_balance = bank.deposit(&key.pubkey(), 10).unwrap();
10510        assert_eq!(new_balance, 10);
10511        assert_eq!(bank.get_balance(&key.pubkey()), 10);
10512
10513        // Existing account
10514        let new_balance = bank.deposit(&key.pubkey(), 3).unwrap();
10515        assert_eq!(new_balance, 13);
10516        assert_eq!(bank.get_balance(&key.pubkey()), 13);
10517    }
10518
10519    #[test]
10520    fn test_bank_withdraw() {
10521        let bank = create_simple_test_bank(100);
10522
10523        // Test no account
10524        let key = Keypair::new();
10525        assert_eq!(
10526            bank.withdraw(&key.pubkey(), 10),
10527            Err(TransactionError::AccountNotFound)
10528        );
10529
10530        bank.deposit(&key.pubkey(), 3).unwrap();
10531        assert_eq!(bank.get_balance(&key.pubkey()), 3);
10532
10533        // Low balance
10534        assert_eq!(
10535            bank.withdraw(&key.pubkey(), 10),
10536            Err(TransactionError::InsufficientFundsForFee)
10537        );
10538
10539        // Enough balance
10540        assert_eq!(bank.withdraw(&key.pubkey(), 2), Ok(()));
10541        assert_eq!(bank.get_balance(&key.pubkey()), 1);
10542    }
10543
10544    #[test]
10545    fn test_bank_withdraw_from_nonce_account() {
10546        let (mut genesis_config, _mint_keypair) = create_genesis_config(100_000);
10547        genesis_config.rent.lamports_per_byte_year = 42;
10548        let bank = Bank::new_for_tests(&genesis_config);
10549
10550        let min_balance = bank.get_minimum_balance_for_rent_exemption(nonce::State::size());
10551        let nonce = Keypair::new();
10552        let nonce_account = AccountSharedData::new_data(
10553            min_balance + 42,
10554            &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data::default())),
10555            &system_program::id(),
10556        )
10557        .unwrap();
10558        bank.store_account(&nonce.pubkey(), &nonce_account);
10559        assert_eq!(bank.get_balance(&nonce.pubkey()), min_balance + 42);
10560
10561        // Resulting in non-zero, but sub-min_balance balance fails
10562        assert_eq!(
10563            bank.withdraw(&nonce.pubkey(), min_balance / 2),
10564            Err(TransactionError::InsufficientFundsForFee)
10565        );
10566        assert_eq!(bank.get_balance(&nonce.pubkey()), min_balance + 42);
10567
10568        // Resulting in exactly rent-exempt balance succeeds
10569        bank.withdraw(&nonce.pubkey(), 42).unwrap();
10570        assert_eq!(bank.get_balance(&nonce.pubkey()), min_balance);
10571
10572        // Account closure fails
10573        assert_eq!(
10574            bank.withdraw(&nonce.pubkey(), min_balance),
10575            Err(TransactionError::InsufficientFundsForFee),
10576        );
10577    }
10578
10579    #[test]
10580    fn test_bank_tx_fee() {
10581        solana_logger::setup();
10582
10583        let arbitrary_transfer_amount = 42_000;
10584        let mint = arbitrary_transfer_amount * 100;
10585        let leader = solana_sdk::pubkey::new_rand();
10586        let GenesisConfigInfo {
10587            mut genesis_config,
10588            mint_keypair,
10589            ..
10590        } = create_genesis_config_with_leader(mint, &leader, 3);
10591        genesis_config.fee_rate_governor = FeeRateGovernor::new(5000, 0); // something divisible by 2
10592
10593        let expected_fee_paid = genesis_config
10594            .fee_rate_governor
10595            .create_fee_calculator()
10596            .lamports_per_signature;
10597        let (expected_fee_collected, expected_fee_burned) =
10598            genesis_config.fee_rate_governor.burn(expected_fee_paid);
10599
10600        let mut bank = Bank::new_for_tests(&genesis_config);
10601
10602        let capitalization = bank.capitalization();
10603
10604        let key = Keypair::new();
10605        let tx = system_transaction::transfer(
10606            &mint_keypair,
10607            &key.pubkey(),
10608            arbitrary_transfer_amount,
10609            bank.last_blockhash(),
10610        );
10611
10612        let initial_balance = bank.get_balance(&leader);
10613        assert_eq!(bank.process_transaction(&tx), Ok(()));
10614        assert_eq!(bank.get_balance(&key.pubkey()), arbitrary_transfer_amount);
10615        assert_eq!(
10616            bank.get_balance(&mint_keypair.pubkey()),
10617            mint - arbitrary_transfer_amount - expected_fee_paid
10618        );
10619
10620        assert_eq!(bank.get_balance(&leader), initial_balance);
10621        goto_end_of_slot(&mut bank);
10622        assert_eq!(bank.signature_count(), 1);
10623        assert_eq!(
10624            bank.get_balance(&leader),
10625            initial_balance + expected_fee_collected
10626        ); // Leader collects fee after the bank is frozen
10627
10628        // verify capitalization
10629        let sysvar_and_builtin_program_delta = 1;
10630        assert_eq!(
10631            capitalization - expected_fee_burned + sysvar_and_builtin_program_delta,
10632            bank.capitalization()
10633        );
10634
10635        assert_eq!(
10636            *bank.rewards.read().unwrap(),
10637            vec![(
10638                leader,
10639                RewardInfo {
10640                    reward_type: RewardType::Fee,
10641                    lamports: expected_fee_collected as i64,
10642                    post_balance: initial_balance + expected_fee_collected,
10643                    commission: None,
10644                }
10645            )]
10646        );
10647
10648        // Verify that an InstructionError collects fees, too
10649        let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
10650        let mut tx =
10651            system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, bank.last_blockhash());
10652        // Create a bogus instruction to system_program to cause an instruction error
10653        tx.message.instructions[0].data[0] = 40;
10654
10655        bank.process_transaction(&tx)
10656            .expect_err("instruction error");
10657        assert_eq!(bank.get_balance(&key.pubkey()), arbitrary_transfer_amount); // no change
10658        assert_eq!(
10659            bank.get_balance(&mint_keypair.pubkey()),
10660            mint - arbitrary_transfer_amount - 2 * expected_fee_paid
10661        ); // mint_keypair still pays a fee
10662        goto_end_of_slot(&mut bank);
10663        assert_eq!(bank.signature_count(), 1);
10664
10665        // Profit! 2 transaction signatures processed at 3 lamports each
10666        assert_eq!(
10667            bank.get_balance(&leader),
10668            initial_balance + 2 * expected_fee_collected
10669        );
10670
10671        assert_eq!(
10672            *bank.rewards.read().unwrap(),
10673            vec![(
10674                leader,
10675                RewardInfo {
10676                    reward_type: RewardType::Fee,
10677                    lamports: expected_fee_collected as i64,
10678                    post_balance: initial_balance + 2 * expected_fee_collected,
10679                    commission: None,
10680                }
10681            )]
10682        );
10683    }
10684
10685    #[test]
10686    fn test_bank_tx_compute_unit_fee() {
10687        solana_logger::setup();
10688
10689        let key = Keypair::new();
10690        let arbitrary_transfer_amount = 42;
10691        let mint = arbitrary_transfer_amount * 10_000_000;
10692        let leader = solana_sdk::pubkey::new_rand();
10693        let GenesisConfigInfo {
10694            mut genesis_config,
10695            mint_keypair,
10696            ..
10697        } = create_genesis_config_with_leader(mint, &leader, 3);
10698        genesis_config.fee_rate_governor = FeeRateGovernor::new(4, 0); // something divisible by 2
10699
10700        let expected_fee_paid = Bank::calculate_fee(
10701            &SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(),
10702            genesis_config
10703                .fee_rate_governor
10704                .create_fee_calculator()
10705                .lamports_per_signature,
10706            &FeeStructure::default(),
10707            true,
10708            true,
10709            true,
10710        );
10711
10712        let (expected_fee_collected, expected_fee_burned) =
10713            genesis_config.fee_rate_governor.burn(expected_fee_paid);
10714
10715        let mut bank = Bank::new_for_tests(&genesis_config);
10716
10717        let capitalization = bank.capitalization();
10718
10719        let tx = system_transaction::transfer(
10720            &mint_keypair,
10721            &key.pubkey(),
10722            arbitrary_transfer_amount,
10723            bank.last_blockhash(),
10724        );
10725
10726        let initial_balance = bank.get_balance(&leader);
10727        assert_eq!(bank.process_transaction(&tx), Ok(()));
10728        assert_eq!(bank.get_balance(&key.pubkey()), arbitrary_transfer_amount);
10729        assert_eq!(
10730            bank.get_balance(&mint_keypair.pubkey()),
10731            mint - arbitrary_transfer_amount - expected_fee_paid
10732        );
10733
10734        assert_eq!(bank.get_balance(&leader), initial_balance);
10735        goto_end_of_slot(&mut bank);
10736        assert_eq!(bank.signature_count(), 1);
10737        assert_eq!(
10738            bank.get_balance(&leader),
10739            initial_balance + expected_fee_collected
10740        ); // Leader collects fee after the bank is frozen
10741
10742        // verify capitalization
10743        let sysvar_and_builtin_program_delta = 1;
10744        assert_eq!(
10745            capitalization - expected_fee_burned + sysvar_and_builtin_program_delta,
10746            bank.capitalization()
10747        );
10748
10749        assert_eq!(
10750            *bank.rewards.read().unwrap(),
10751            vec![(
10752                leader,
10753                RewardInfo {
10754                    reward_type: RewardType::Fee,
10755                    lamports: expected_fee_collected as i64,
10756                    post_balance: initial_balance + expected_fee_collected,
10757                    commission: None,
10758                }
10759            )]
10760        );
10761
10762        // Verify that an InstructionError collects fees, too
10763        let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
10764        let mut tx =
10765            system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, bank.last_blockhash());
10766        // Create a bogus instruction to system_program to cause an instruction error
10767        tx.message.instructions[0].data[0] = 40;
10768
10769        bank.process_transaction(&tx)
10770            .expect_err("instruction error");
10771        assert_eq!(bank.get_balance(&key.pubkey()), arbitrary_transfer_amount); // no change
10772        assert_eq!(
10773            bank.get_balance(&mint_keypair.pubkey()),
10774            mint - arbitrary_transfer_amount - 2 * expected_fee_paid
10775        ); // mint_keypair still pays a fee
10776        goto_end_of_slot(&mut bank);
10777        assert_eq!(bank.signature_count(), 1);
10778
10779        // Profit! 2 transaction signatures processed at 3 lamports each
10780        assert_eq!(
10781            bank.get_balance(&leader),
10782            initial_balance + 2 * expected_fee_collected
10783        );
10784
10785        assert_eq!(
10786            *bank.rewards.read().unwrap(),
10787            vec![(
10788                leader,
10789                RewardInfo {
10790                    reward_type: RewardType::Fee,
10791                    lamports: expected_fee_collected as i64,
10792                    post_balance: initial_balance + 2 * expected_fee_collected,
10793                    commission: None,
10794                }
10795            )]
10796        );
10797    }
10798
10799    #[test]
10800    fn test_bank_blockhash_fee_structure() {
10801        //solana_logger::setup();
10802
10803        let leader = solana_sdk::pubkey::new_rand();
10804        let GenesisConfigInfo {
10805            mut genesis_config,
10806            mint_keypair,
10807            ..
10808        } = create_genesis_config_with_leader(1_000_000, &leader, 3);
10809        genesis_config
10810            .fee_rate_governor
10811            .target_lamports_per_signature = 5000;
10812        genesis_config.fee_rate_governor.target_signatures_per_slot = 0;
10813
10814        let mut bank = Bank::new_for_tests(&genesis_config);
10815        goto_end_of_slot(&mut bank);
10816        let cheap_blockhash = bank.last_blockhash();
10817        let cheap_lamports_per_signature = bank.get_lamports_per_signature();
10818        assert_eq!(cheap_lamports_per_signature, 0);
10819
10820        let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
10821        goto_end_of_slot(&mut bank);
10822        let expensive_blockhash = bank.last_blockhash();
10823        let expensive_lamports_per_signature = bank.get_lamports_per_signature();
10824        assert!(cheap_lamports_per_signature < expensive_lamports_per_signature);
10825
10826        let bank = Bank::new_from_parent(&Arc::new(bank), &leader, 2);
10827
10828        // Send a transfer using cheap_blockhash
10829        let key = Keypair::new();
10830        let initial_mint_balance = bank.get_balance(&mint_keypair.pubkey());
10831        let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, cheap_blockhash);
10832        assert_eq!(bank.process_transaction(&tx), Ok(()));
10833        assert_eq!(bank.get_balance(&key.pubkey()), 1);
10834        assert_eq!(
10835            bank.get_balance(&mint_keypair.pubkey()),
10836            initial_mint_balance - 1 - cheap_lamports_per_signature
10837        );
10838
10839        // Send a transfer using expensive_blockhash
10840        let key = Keypair::new();
10841        let initial_mint_balance = bank.get_balance(&mint_keypair.pubkey());
10842        let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, expensive_blockhash);
10843        assert_eq!(bank.process_transaction(&tx), Ok(()));
10844        assert_eq!(bank.get_balance(&key.pubkey()), 1);
10845        assert_eq!(
10846            bank.get_balance(&mint_keypair.pubkey()),
10847            initial_mint_balance - 1 - expensive_lamports_per_signature
10848        );
10849    }
10850
10851    #[test]
10852    fn test_bank_blockhash_compute_unit_fee_structure() {
10853        //solana_logger::setup();
10854
10855        let leader = solana_sdk::pubkey::new_rand();
10856        let GenesisConfigInfo {
10857            mut genesis_config,
10858            mint_keypair,
10859            ..
10860        } = create_genesis_config_with_leader(1_000_000_000, &leader, 3);
10861        genesis_config
10862            .fee_rate_governor
10863            .target_lamports_per_signature = 1000;
10864        genesis_config.fee_rate_governor.target_signatures_per_slot = 1;
10865
10866        let mut bank = Bank::new_for_tests(&genesis_config);
10867        goto_end_of_slot(&mut bank);
10868        let cheap_blockhash = bank.last_blockhash();
10869        let cheap_lamports_per_signature = bank.get_lamports_per_signature();
10870        assert_eq!(cheap_lamports_per_signature, 0);
10871
10872        let mut bank = Bank::new_from_parent(&Arc::new(bank), &leader, 1);
10873        goto_end_of_slot(&mut bank);
10874        let expensive_blockhash = bank.last_blockhash();
10875        let expensive_lamports_per_signature = bank.get_lamports_per_signature();
10876        assert!(cheap_lamports_per_signature < expensive_lamports_per_signature);
10877
10878        let bank = Bank::new_from_parent(&Arc::new(bank), &leader, 2);
10879
10880        // Send a transfer using cheap_blockhash
10881        let key = Keypair::new();
10882        let initial_mint_balance = bank.get_balance(&mint_keypair.pubkey());
10883        let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, cheap_blockhash);
10884        assert_eq!(bank.process_transaction(&tx), Ok(()));
10885        assert_eq!(bank.get_balance(&key.pubkey()), 1);
10886        let cheap_fee = Bank::calculate_fee(
10887            &SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(),
10888            cheap_lamports_per_signature,
10889            &FeeStructure::default(),
10890            true,
10891            true,
10892            true,
10893        );
10894        assert_eq!(
10895            bank.get_balance(&mint_keypair.pubkey()),
10896            initial_mint_balance - 1 - cheap_fee
10897        );
10898
10899        // Send a transfer using expensive_blockhash
10900        let key = Keypair::new();
10901        let initial_mint_balance = bank.get_balance(&mint_keypair.pubkey());
10902        let tx = system_transaction::transfer(&mint_keypair, &key.pubkey(), 1, expensive_blockhash);
10903        assert_eq!(bank.process_transaction(&tx), Ok(()));
10904        assert_eq!(bank.get_balance(&key.pubkey()), 1);
10905        let expensive_fee = Bank::calculate_fee(
10906            &SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap(),
10907            expensive_lamports_per_signature,
10908            &FeeStructure::default(),
10909            true,
10910            true,
10911            true,
10912        );
10913        assert_eq!(
10914            bank.get_balance(&mint_keypair.pubkey()),
10915            initial_mint_balance - 1 - expensive_fee
10916        );
10917    }
10918
10919    #[test]
10920    fn test_filter_program_errors_and_collect_fee() {
10921        let leader = solana_sdk::pubkey::new_rand();
10922        let GenesisConfigInfo {
10923            mut genesis_config,
10924            mint_keypair,
10925            ..
10926        } = create_genesis_config_with_leader(100_000, &leader, 3);
10927        genesis_config.fee_rate_governor = FeeRateGovernor::new(5000, 0);
10928        let bank = Bank::new_for_tests(&genesis_config);
10929
10930        let key = Keypair::new();
10931        let tx1 = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer(
10932            &mint_keypair,
10933            &key.pubkey(),
10934            2,
10935            genesis_config.hash(),
10936        ));
10937        let tx2 = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer(
10938            &mint_keypair,
10939            &key.pubkey(),
10940            5,
10941            genesis_config.hash(),
10942        ));
10943
10944        let results = vec![
10945            new_execution_result(Ok(()), None),
10946            new_execution_result(
10947                Err(TransactionError::InstructionError(
10948                    1,
10949                    SystemError::ResultWithNegativeLamports.into(),
10950                )),
10951                None,
10952            ),
10953        ];
10954        let initial_balance = bank.get_balance(&leader);
10955
10956        let results = bank.filter_program_errors_and_collect_fee(&[tx1, tx2], &results);
10957        bank.freeze();
10958        assert_eq!(
10959            bank.get_balance(&leader),
10960            initial_balance
10961                + bank
10962                    .fee_rate_governor
10963                    .burn(bank.fee_rate_governor.lamports_per_signature * 2)
10964                    .0
10965        );
10966        assert_eq!(results[0], Ok(()));
10967        assert_eq!(results[1], Ok(()));
10968    }
10969
10970    #[test]
10971    fn test_filter_program_errors_and_collect_compute_unit_fee() {
10972        let leader = solana_sdk::pubkey::new_rand();
10973        let GenesisConfigInfo {
10974            mut genesis_config,
10975            mint_keypair,
10976            ..
10977        } = create_genesis_config_with_leader(1000000, &leader, 3);
10978        genesis_config.fee_rate_governor = FeeRateGovernor::new(2, 0);
10979        let bank = Bank::new_for_tests(&genesis_config);
10980
10981        let key = Keypair::new();
10982        let tx1 = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer(
10983            &mint_keypair,
10984            &key.pubkey(),
10985            2,
10986            genesis_config.hash(),
10987        ));
10988        let tx2 = SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer(
10989            &mint_keypair,
10990            &key.pubkey(),
10991            5,
10992            genesis_config.hash(),
10993        ));
10994
10995        let results = vec![
10996            new_execution_result(Ok(()), None),
10997            new_execution_result(
10998                Err(TransactionError::InstructionError(
10999                    1,
11000                    SystemError::ResultWithNegativeLamports.into(),
11001                )),
11002                None,
11003            ),
11004        ];
11005        let initial_balance = bank.get_balance(&leader);
11006
11007        let results = bank.filter_program_errors_and_collect_fee(&[tx1, tx2], &results);
11008        bank.freeze();
11009        assert_eq!(
11010            bank.get_balance(&leader),
11011            initial_balance
11012                + bank
11013                    .fee_rate_governor
11014                    .burn(
11015                        Bank::calculate_fee(
11016                            &SanitizedMessage::try_from(Message::new(
11017                                &[],
11018                                Some(&Pubkey::new_unique())
11019                            ))
11020                            .unwrap(),
11021                            genesis_config
11022                                .fee_rate_governor
11023                                .create_fee_calculator()
11024                                .lamports_per_signature,
11025                            &FeeStructure::default(),
11026                            true,
11027                            true,
11028                            true,
11029                        ) * 2
11030                    )
11031                    .0
11032        );
11033        assert_eq!(results[0], Ok(()));
11034        assert_eq!(results[1], Ok(()));
11035    }
11036
11037    #[test]
11038    fn test_debits_before_credits() {
11039        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(2.));
11040        let bank = Bank::new_for_tests(&genesis_config);
11041        let keypair = Keypair::new();
11042        let tx0 = system_transaction::transfer(
11043            &mint_keypair,
11044            &keypair.pubkey(),
11045            sol_to_lamports(2.),
11046            genesis_config.hash(),
11047        );
11048        let tx1 = system_transaction::transfer(
11049            &keypair,
11050            &mint_keypair.pubkey(),
11051            sol_to_lamports(1.),
11052            genesis_config.hash(),
11053        );
11054        let txs = vec![tx0, tx1];
11055        let results = bank.process_transactions(txs.iter());
11056        assert!(results[1].is_err());
11057
11058        // Assert bad transactions aren't counted.
11059        assert_eq!(bank.transaction_count(), 1);
11060    }
11061
11062    #[test]
11063    fn test_readonly_accounts() {
11064        let GenesisConfigInfo {
11065            genesis_config,
11066            mint_keypair,
11067            ..
11068        } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 0);
11069        let bank = Bank::new_for_tests(&genesis_config);
11070
11071        let vote_pubkey0 = solana_sdk::pubkey::new_rand();
11072        let vote_pubkey1 = solana_sdk::pubkey::new_rand();
11073        let vote_pubkey2 = solana_sdk::pubkey::new_rand();
11074        let authorized_voter = Keypair::new();
11075        let payer0 = Keypair::new();
11076        let payer1 = Keypair::new();
11077
11078        // Create vote accounts
11079        let vote_account0 =
11080            vote_state::create_account(&vote_pubkey0, &authorized_voter.pubkey(), 0, 100);
11081        let vote_account1 =
11082            vote_state::create_account(&vote_pubkey1, &authorized_voter.pubkey(), 0, 100);
11083        let vote_account2 =
11084            vote_state::create_account(&vote_pubkey2, &authorized_voter.pubkey(), 0, 100);
11085        bank.store_account(&vote_pubkey0, &vote_account0);
11086        bank.store_account(&vote_pubkey1, &vote_account1);
11087        bank.store_account(&vote_pubkey2, &vote_account2);
11088
11089        // Fund payers
11090        bank.transfer(10, &mint_keypair, &payer0.pubkey()).unwrap();
11091        bank.transfer(10, &mint_keypair, &payer1.pubkey()).unwrap();
11092        bank.transfer(1, &mint_keypair, &authorized_voter.pubkey())
11093            .unwrap();
11094
11095        let vote = Vote::new(vec![1], Hash::default());
11096        let ix0 = vote_instruction::vote(&vote_pubkey0, &authorized_voter.pubkey(), vote.clone());
11097        let tx0 = Transaction::new_signed_with_payer(
11098            &[ix0],
11099            Some(&payer0.pubkey()),
11100            &[&payer0, &authorized_voter],
11101            bank.last_blockhash(),
11102        );
11103        let ix1 = vote_instruction::vote(&vote_pubkey1, &authorized_voter.pubkey(), vote.clone());
11104        let tx1 = Transaction::new_signed_with_payer(
11105            &[ix1],
11106            Some(&payer1.pubkey()),
11107            &[&payer1, &authorized_voter],
11108            bank.last_blockhash(),
11109        );
11110        let txs = vec![tx0, tx1];
11111        let results = bank.process_transactions(txs.iter());
11112
11113        // If multiple transactions attempt to read the same account, they should succeed.
11114        // Vote authorized_voter and sysvar accounts are given read-only handling
11115        assert_eq!(results[0], Ok(()));
11116        assert_eq!(results[1], Ok(()));
11117
11118        let ix0 = vote_instruction::vote(&vote_pubkey2, &authorized_voter.pubkey(), vote);
11119        let tx0 = Transaction::new_signed_with_payer(
11120            &[ix0],
11121            Some(&payer0.pubkey()),
11122            &[&payer0, &authorized_voter],
11123            bank.last_blockhash(),
11124        );
11125        let tx1 = system_transaction::transfer(
11126            &authorized_voter,
11127            &solana_sdk::pubkey::new_rand(),
11128            1,
11129            bank.last_blockhash(),
11130        );
11131        let txs = vec![tx0, tx1];
11132        let results = bank.process_transactions(txs.iter());
11133        // However, an account may not be locked as read-only and writable at the same time.
11134        assert_eq!(results[0], Ok(()));
11135        assert_eq!(results[1], Err(TransactionError::AccountInUse));
11136    }
11137
11138    #[test]
11139    fn test_interleaving_locks() {
11140        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11141        let bank = Bank::new_for_tests(&genesis_config);
11142        let alice = Keypair::new();
11143        let bob = Keypair::new();
11144        let amount = genesis_config.rent.minimum_balance(0);
11145
11146        let tx1 = system_transaction::transfer(
11147            &mint_keypair,
11148            &alice.pubkey(),
11149            amount,
11150            genesis_config.hash(),
11151        );
11152        let pay_alice = vec![tx1];
11153
11154        let lock_result = bank.prepare_batch_for_tests(pay_alice);
11155        let results_alice = bank
11156            .load_execute_and_commit_transactions(
11157                &lock_result,
11158                MAX_PROCESSING_AGE,
11159                false,
11160                false,
11161                false,
11162                false,
11163                &mut ExecuteTimings::default(),
11164                None,
11165            )
11166            .0
11167            .fee_collection_results;
11168        assert_eq!(results_alice[0], Ok(()));
11169
11170        // try executing an interleaved transfer twice
11171        assert_eq!(
11172            bank.transfer(amount, &mint_keypair, &bob.pubkey()),
11173            Err(TransactionError::AccountInUse)
11174        );
11175        // the second time should fail as well
11176        // this verifies that `unlock_accounts` doesn't unlock `AccountInUse` accounts
11177        assert_eq!(
11178            bank.transfer(amount, &mint_keypair, &bob.pubkey()),
11179            Err(TransactionError::AccountInUse)
11180        );
11181
11182        drop(lock_result);
11183
11184        assert!(bank
11185            .transfer(2 * amount, &mint_keypair, &bob.pubkey())
11186            .is_ok());
11187    }
11188
11189    #[test]
11190    fn test_readonly_relaxed_locks() {
11191        let (genesis_config, _) = create_genesis_config(3);
11192        let bank = Bank::new_for_tests(&genesis_config);
11193        let key0 = Keypair::new();
11194        let key1 = Keypair::new();
11195        let key2 = Keypair::new();
11196        let key3 = solana_sdk::pubkey::new_rand();
11197
11198        let message = Message {
11199            header: MessageHeader {
11200                num_required_signatures: 1,
11201                num_readonly_signed_accounts: 0,
11202                num_readonly_unsigned_accounts: 1,
11203            },
11204            account_keys: vec![key0.pubkey(), key3],
11205            recent_blockhash: Hash::default(),
11206            instructions: vec![],
11207        };
11208        let tx = Transaction::new(&[&key0], message, genesis_config.hash());
11209        let txs = vec![tx];
11210
11211        let batch0 = bank.prepare_batch_for_tests(txs);
11212        assert!(batch0.lock_results()[0].is_ok());
11213
11214        // Try locking accounts, locking a previously read-only account as writable
11215        // should fail
11216        let message = Message {
11217            header: MessageHeader {
11218                num_required_signatures: 1,
11219                num_readonly_signed_accounts: 0,
11220                num_readonly_unsigned_accounts: 0,
11221            },
11222            account_keys: vec![key1.pubkey(), key3],
11223            recent_blockhash: Hash::default(),
11224            instructions: vec![],
11225        };
11226        let tx = Transaction::new(&[&key1], message, genesis_config.hash());
11227        let txs = vec![tx];
11228
11229        let batch1 = bank.prepare_batch_for_tests(txs);
11230        assert!(batch1.lock_results()[0].is_err());
11231
11232        // Try locking a previously read-only account a 2nd time; should succeed
11233        let message = Message {
11234            header: MessageHeader {
11235                num_required_signatures: 1,
11236                num_readonly_signed_accounts: 0,
11237                num_readonly_unsigned_accounts: 1,
11238            },
11239            account_keys: vec![key2.pubkey(), key3],
11240            recent_blockhash: Hash::default(),
11241            instructions: vec![],
11242        };
11243        let tx = Transaction::new(&[&key2], message, genesis_config.hash());
11244        let txs = vec![tx];
11245
11246        let batch2 = bank.prepare_batch_for_tests(txs);
11247        assert!(batch2.lock_results()[0].is_ok());
11248    }
11249
11250    #[test]
11251    fn test_bank_invalid_account_index() {
11252        let (genesis_config, mint_keypair) = create_genesis_config(1);
11253        let keypair = Keypair::new();
11254        let bank = Bank::new_for_tests(&genesis_config);
11255
11256        let tx = system_transaction::transfer(
11257            &mint_keypair,
11258            &keypair.pubkey(),
11259            1,
11260            genesis_config.hash(),
11261        );
11262
11263        let mut tx_invalid_program_index = tx.clone();
11264        tx_invalid_program_index.message.instructions[0].program_id_index = 42;
11265        assert_eq!(
11266            bank.process_transaction(&tx_invalid_program_index),
11267            Err(TransactionError::SanitizeFailure)
11268        );
11269
11270        let mut tx_invalid_account_index = tx;
11271        tx_invalid_account_index.message.instructions[0].accounts[0] = 42;
11272        assert_eq!(
11273            bank.process_transaction(&tx_invalid_account_index),
11274            Err(TransactionError::SanitizeFailure)
11275        );
11276    }
11277
11278    #[test]
11279    fn test_bank_pay_to_self() {
11280        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11281        let key1 = Keypair::new();
11282        let bank = Bank::new_for_tests(&genesis_config);
11283        let amount = genesis_config.rent.minimum_balance(0);
11284
11285        bank.transfer(amount, &mint_keypair, &key1.pubkey())
11286            .unwrap();
11287        assert_eq!(bank.get_balance(&key1.pubkey()), amount);
11288        let tx = system_transaction::transfer(&key1, &key1.pubkey(), amount, genesis_config.hash());
11289        let _res = bank.process_transaction(&tx);
11290
11291        assert_eq!(bank.get_balance(&key1.pubkey()), amount);
11292        bank.get_signature_status(&tx.signatures[0])
11293            .unwrap()
11294            .unwrap();
11295    }
11296
11297    fn new_from_parent(parent: &Arc<Bank>) -> Bank {
11298        Bank::new_from_parent(parent, &Pubkey::default(), parent.slot() + 1)
11299    }
11300
11301    /// Verify that the parent's vector is computed correctly
11302    #[test]
11303    fn test_bank_parents() {
11304        let (genesis_config, _) = create_genesis_config(1);
11305        let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11306
11307        let bank = new_from_parent(&parent);
11308        assert!(Arc::ptr_eq(&bank.parents()[0], &parent));
11309    }
11310
11311    /// Verifies that transactions are dropped if they have already been processed
11312    #[test]
11313    fn test_tx_already_processed() {
11314        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11315        let bank = Bank::new_for_tests(&genesis_config);
11316
11317        let key1 = Keypair::new();
11318        let mut tx = system_transaction::transfer(
11319            &mint_keypair,
11320            &key1.pubkey(),
11321            genesis_config.rent.minimum_balance(0),
11322            genesis_config.hash(),
11323        );
11324
11325        // First process `tx` so that the status cache is updated
11326        assert_eq!(bank.process_transaction(&tx), Ok(()));
11327
11328        // Ensure that signature check works
11329        assert_eq!(
11330            bank.process_transaction(&tx),
11331            Err(TransactionError::AlreadyProcessed)
11332        );
11333
11334        // Change transaction signature to simulate processing a transaction with a different signature
11335        // for the same message.
11336        tx.signatures[0] = Signature::default();
11337
11338        // Ensure that message hash check works
11339        assert_eq!(
11340            bank.process_transaction(&tx),
11341            Err(TransactionError::AlreadyProcessed)
11342        );
11343    }
11344
11345    /// Verifies that last ids and status cache are correctly referenced from parent
11346    #[test]
11347    fn test_bank_parent_already_processed() {
11348        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11349        let key1 = Keypair::new();
11350        let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11351        let amount = genesis_config.rent.minimum_balance(0);
11352
11353        let tx = system_transaction::transfer(
11354            &mint_keypair,
11355            &key1.pubkey(),
11356            amount,
11357            genesis_config.hash(),
11358        );
11359        assert_eq!(parent.process_transaction(&tx), Ok(()));
11360        let bank = new_from_parent(&parent);
11361        assert_eq!(
11362            bank.process_transaction(&tx),
11363            Err(TransactionError::AlreadyProcessed)
11364        );
11365    }
11366
11367    /// Verifies that last ids and accounts are correctly referenced from parent
11368    #[test]
11369    fn test_bank_parent_account_spend() {
11370        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
11371        let key1 = Keypair::new();
11372        let key2 = Keypair::new();
11373        let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11374        let amount = genesis_config.rent.minimum_balance(0);
11375
11376        let tx = system_transaction::transfer(
11377            &mint_keypair,
11378            &key1.pubkey(),
11379            amount,
11380            genesis_config.hash(),
11381        );
11382        assert_eq!(parent.process_transaction(&tx), Ok(()));
11383        let bank = new_from_parent(&parent);
11384        let tx = system_transaction::transfer(&key1, &key2.pubkey(), amount, genesis_config.hash());
11385        assert_eq!(bank.process_transaction(&tx), Ok(()));
11386        assert_eq!(parent.get_signature_status(&tx.signatures[0]), None);
11387    }
11388
11389    #[test]
11390    fn test_bank_hash_internal_state() {
11391        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11392        let bank0 = Bank::new_for_tests(&genesis_config);
11393        let bank1 = Bank::new_for_tests(&genesis_config);
11394        let amount = genesis_config.rent.minimum_balance(0);
11395        let initial_state = bank0.hash_internal_state();
11396        assert_eq!(bank1.hash_internal_state(), initial_state);
11397
11398        let pubkey = solana_sdk::pubkey::new_rand();
11399        bank0.transfer(amount, &mint_keypair, &pubkey).unwrap();
11400        assert_ne!(bank0.hash_internal_state(), initial_state);
11401        bank1.transfer(amount, &mint_keypair, &pubkey).unwrap();
11402        assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
11403
11404        // Checkpointing should always result in a new state
11405        let bank2 = new_from_parent(&Arc::new(bank1));
11406        assert_ne!(bank0.hash_internal_state(), bank2.hash_internal_state());
11407
11408        let pubkey2 = solana_sdk::pubkey::new_rand();
11409        info!("transfer 2 {}", pubkey2);
11410        bank2.transfer(amount, &mint_keypair, &pubkey2).unwrap();
11411        bank2.update_accounts_hash();
11412        assert!(bank2.verify_bank_hash(VerifyBankHash::default_for_test()));
11413    }
11414
11415    #[test]
11416    fn test_bank_hash_internal_state_verify() {
11417        solana_logger::setup();
11418        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11419        let bank0 = Bank::new_for_tests(&genesis_config);
11420        let amount = genesis_config.rent.minimum_balance(0);
11421
11422        let pubkey = solana_sdk::pubkey::new_rand();
11423        info!("transfer 0 {} mint: {}", pubkey, mint_keypair.pubkey());
11424        bank0.transfer(amount, &mint_keypair, &pubkey).unwrap();
11425
11426        let bank0_state = bank0.hash_internal_state();
11427        let bank0 = Arc::new(bank0);
11428        // Checkpointing should result in a new state while freezing the parent
11429        let bank2 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 1);
11430        assert_ne!(bank0_state, bank2.hash_internal_state());
11431        // Checkpointing should modify the checkpoint's state when freezed
11432        assert_ne!(bank0_state, bank0.hash_internal_state());
11433
11434        // Checkpointing should never modify the checkpoint's state once frozen
11435        let bank0_state = bank0.hash_internal_state();
11436        bank2.update_accounts_hash();
11437        assert!(bank2.verify_bank_hash(VerifyBankHash::default_for_test()));
11438        let bank3 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 2);
11439        assert_eq!(bank0_state, bank0.hash_internal_state());
11440        assert!(bank2.verify_bank_hash(VerifyBankHash::default_for_test()));
11441        bank3.update_accounts_hash();
11442        assert!(bank3.verify_bank_hash(VerifyBankHash::default_for_test()));
11443
11444        let pubkey2 = solana_sdk::pubkey::new_rand();
11445        info!("transfer 2 {}", pubkey2);
11446        bank2.transfer(amount, &mint_keypair, &pubkey2).unwrap();
11447        bank2.update_accounts_hash();
11448        assert!(bank2.verify_bank_hash(VerifyBankHash::default_for_test()));
11449        assert!(bank3.verify_bank_hash(VerifyBankHash::default_for_test()));
11450    }
11451
11452    #[test]
11453    #[should_panic(expected = "assertion failed: self.is_frozen()")]
11454    fn test_verify_hash_unfrozen() {
11455        let bank = create_simple_test_bank(2_000);
11456        assert!(bank.verify_hash());
11457    }
11458
11459    #[test]
11460    fn test_verify_snapshot_bank() {
11461        solana_logger::setup();
11462        let pubkey = solana_sdk::pubkey::new_rand();
11463        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11464        let bank = Bank::new_for_tests(&genesis_config);
11465        bank.transfer(
11466            genesis_config.rent.minimum_balance(0),
11467            &mint_keypair,
11468            &pubkey,
11469        )
11470        .unwrap();
11471        bank.freeze();
11472        bank.update_accounts_hash();
11473        assert!(bank.verify_snapshot_bank(true, false, None));
11474
11475        // tamper the bank after freeze!
11476        bank.increment_signature_count(1);
11477        assert!(!bank.verify_snapshot_bank(true, false, None));
11478    }
11479
11480    // Test that two bank forks with the same accounts should not hash to the same value.
11481    #[test]
11482    fn test_bank_hash_internal_state_same_account_different_fork() {
11483        solana_logger::setup();
11484        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11485        let amount = genesis_config.rent.minimum_balance(0);
11486        let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
11487        let initial_state = bank0.hash_internal_state();
11488        let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
11489        assert_ne!(bank1.hash_internal_state(), initial_state);
11490
11491        info!("transfer bank1");
11492        let pubkey = solana_sdk::pubkey::new_rand();
11493        bank1.transfer(amount, &mint_keypair, &pubkey).unwrap();
11494        assert_ne!(bank1.hash_internal_state(), initial_state);
11495
11496        info!("transfer bank2");
11497        // bank2 should not hash the same as bank1
11498        let bank2 = Bank::new_from_parent(&bank0, &Pubkey::default(), 2);
11499        bank2.transfer(amount, &mint_keypair, &pubkey).unwrap();
11500        assert_ne!(bank2.hash_internal_state(), initial_state);
11501        assert_ne!(bank1.hash_internal_state(), bank2.hash_internal_state());
11502    }
11503
11504    #[test]
11505    fn test_hash_internal_state_genesis() {
11506        let bank0 = Bank::new_for_tests(&create_genesis_config(10).0);
11507        let bank1 = Bank::new_for_tests(&create_genesis_config(20).0);
11508        assert_ne!(bank0.hash_internal_state(), bank1.hash_internal_state());
11509    }
11510
11511    // See that the order of two transfers does not affect the result
11512    // of hash_internal_state
11513    #[test]
11514    fn test_hash_internal_state_order() {
11515        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11516        let amount = genesis_config.rent.minimum_balance(0);
11517        let bank0 = Bank::new_for_tests(&genesis_config);
11518        let bank1 = Bank::new_for_tests(&genesis_config);
11519        assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
11520        let key0 = solana_sdk::pubkey::new_rand();
11521        let key1 = solana_sdk::pubkey::new_rand();
11522        bank0.transfer(amount, &mint_keypair, &key0).unwrap();
11523        bank0.transfer(amount * 2, &mint_keypair, &key1).unwrap();
11524
11525        bank1.transfer(amount * 2, &mint_keypair, &key1).unwrap();
11526        bank1.transfer(amount, &mint_keypair, &key0).unwrap();
11527
11528        assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
11529    }
11530
11531    #[test]
11532    fn test_hash_internal_state_error() {
11533        solana_logger::setup();
11534        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11535        let amount = genesis_config.rent.minimum_balance(0);
11536        let bank = Bank::new_for_tests(&genesis_config);
11537        let key0 = solana_sdk::pubkey::new_rand();
11538        bank.transfer(amount, &mint_keypair, &key0).unwrap();
11539        let orig = bank.hash_internal_state();
11540
11541        // Transfer will error but still take a fee
11542        assert!(bank
11543            .transfer(sol_to_lamports(1.), &mint_keypair, &key0)
11544            .is_err());
11545        assert_ne!(orig, bank.hash_internal_state());
11546
11547        let orig = bank.hash_internal_state();
11548        let empty_keypair = Keypair::new();
11549        assert!(bank.transfer(amount, &empty_keypair, &key0).is_err());
11550        assert_eq!(orig, bank.hash_internal_state());
11551    }
11552
11553    #[test]
11554    fn test_bank_hash_internal_state_squash() {
11555        let collector_id = Pubkey::default();
11556        let bank0 = Arc::new(Bank::new_for_tests(&create_genesis_config(10).0));
11557        let hash0 = bank0.hash_internal_state();
11558        // save hash0 because new_from_parent
11559        // updates sysvar entries
11560
11561        let bank1 = Bank::new_from_parent(&bank0, &collector_id, 1);
11562
11563        // no delta in bank1, hashes should always update
11564        assert_ne!(hash0, bank1.hash_internal_state());
11565
11566        // remove parent
11567        bank1.squash();
11568        assert!(bank1.parents().is_empty());
11569    }
11570
11571    /// Verifies that last ids and accounts are correctly referenced from parent
11572    #[test]
11573    fn test_bank_squash() {
11574        solana_logger::setup();
11575        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(2.));
11576        let key1 = Keypair::new();
11577        let key2 = Keypair::new();
11578        let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11579        let amount = genesis_config.rent.minimum_balance(0);
11580
11581        let tx_transfer_mint_to_1 = system_transaction::transfer(
11582            &mint_keypair,
11583            &key1.pubkey(),
11584            amount,
11585            genesis_config.hash(),
11586        );
11587        trace!("parent process tx ");
11588        assert_eq!(parent.process_transaction(&tx_transfer_mint_to_1), Ok(()));
11589        trace!("done parent process tx ");
11590        assert_eq!(parent.transaction_count(), 1);
11591        assert_eq!(
11592            parent.get_signature_status(&tx_transfer_mint_to_1.signatures[0]),
11593            Some(Ok(()))
11594        );
11595
11596        trace!("new from parent");
11597        let bank = new_from_parent(&parent);
11598        trace!("done new from parent");
11599        assert_eq!(
11600            bank.get_signature_status(&tx_transfer_mint_to_1.signatures[0]),
11601            Some(Ok(()))
11602        );
11603
11604        assert_eq!(bank.transaction_count(), parent.transaction_count());
11605        let tx_transfer_1_to_2 =
11606            system_transaction::transfer(&key1, &key2.pubkey(), amount, genesis_config.hash());
11607        assert_eq!(bank.process_transaction(&tx_transfer_1_to_2), Ok(()));
11608        assert_eq!(bank.transaction_count(), 2);
11609        assert_eq!(parent.transaction_count(), 1);
11610        assert_eq!(
11611            parent.get_signature_status(&tx_transfer_1_to_2.signatures[0]),
11612            None
11613        );
11614
11615        for _ in 0..3 {
11616            // first time these should match what happened above, assert that parents are ok
11617            assert_eq!(bank.get_balance(&key1.pubkey()), 0);
11618            assert_eq!(bank.get_account(&key1.pubkey()), None);
11619            assert_eq!(bank.get_balance(&key2.pubkey()), amount);
11620            trace!("start");
11621            assert_eq!(
11622                bank.get_signature_status(&tx_transfer_mint_to_1.signatures[0]),
11623                Some(Ok(()))
11624            );
11625            assert_eq!(
11626                bank.get_signature_status(&tx_transfer_1_to_2.signatures[0]),
11627                Some(Ok(()))
11628            );
11629
11630            // works iteration 0, no-ops on iteration 1 and 2
11631            trace!("SQUASH");
11632            bank.squash();
11633
11634            assert_eq!(parent.transaction_count(), 1);
11635            assert_eq!(bank.transaction_count(), 2);
11636        }
11637    }
11638
11639    #[test]
11640    fn test_bank_get_account_in_parent_after_squash() {
11641        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11642        let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11643        let amount = genesis_config.rent.minimum_balance(0);
11644
11645        let key1 = Keypair::new();
11646
11647        parent
11648            .transfer(amount, &mint_keypair, &key1.pubkey())
11649            .unwrap();
11650        assert_eq!(parent.get_balance(&key1.pubkey()), amount);
11651        let bank = new_from_parent(&parent);
11652        bank.squash();
11653        assert_eq!(parent.get_balance(&key1.pubkey()), amount);
11654    }
11655
11656    #[test]
11657    fn test_bank_get_account_in_parent_after_squash2() {
11658        solana_logger::setup();
11659        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11660        let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
11661        let amount = genesis_config.rent.minimum_balance(0);
11662
11663        let key1 = Keypair::new();
11664
11665        bank0
11666            .transfer(amount, &mint_keypair, &key1.pubkey())
11667            .unwrap();
11668        assert_eq!(bank0.get_balance(&key1.pubkey()), amount);
11669
11670        let bank1 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 1));
11671        bank1
11672            .transfer(3 * amount, &mint_keypair, &key1.pubkey())
11673            .unwrap();
11674        let bank2 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 2));
11675        bank2
11676            .transfer(2 * amount, &mint_keypair, &key1.pubkey())
11677            .unwrap();
11678        let bank3 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 3));
11679        bank1.squash();
11680
11681        // This picks up the values from 1 which is the highest root:
11682        // TODO: if we need to access rooted banks older than this,
11683        // need to fix the lookup.
11684        assert_eq!(bank0.get_balance(&key1.pubkey()), 4 * amount);
11685        assert_eq!(bank3.get_balance(&key1.pubkey()), 4 * amount);
11686        assert_eq!(bank2.get_balance(&key1.pubkey()), 3 * amount);
11687        bank3.squash();
11688        assert_eq!(bank1.get_balance(&key1.pubkey()), 4 * amount);
11689
11690        let bank4 = Arc::new(Bank::new_from_parent(&bank3, &Pubkey::default(), 4));
11691        bank4
11692            .transfer(4 * amount, &mint_keypair, &key1.pubkey())
11693            .unwrap();
11694        assert_eq!(bank4.get_balance(&key1.pubkey()), 8 * amount);
11695        assert_eq!(bank3.get_balance(&key1.pubkey()), 4 * amount);
11696        bank4.squash();
11697        let bank5 = Arc::new(Bank::new_from_parent(&bank4, &Pubkey::default(), 5));
11698        bank5.squash();
11699        let bank6 = Arc::new(Bank::new_from_parent(&bank5, &Pubkey::default(), 6));
11700        bank6.squash();
11701
11702        // This picks up the values from 4 which is the highest root:
11703        // TODO: if we need to access rooted banks older than this,
11704        // need to fix the lookup.
11705        assert_eq!(bank3.get_balance(&key1.pubkey()), 8 * amount);
11706        assert_eq!(bank2.get_balance(&key1.pubkey()), 8 * amount);
11707
11708        assert_eq!(bank4.get_balance(&key1.pubkey()), 8 * amount);
11709    }
11710
11711    #[test]
11712    fn test_bank_get_account_modified_since_parent_with_fixed_root() {
11713        let pubkey = solana_sdk::pubkey::new_rand();
11714
11715        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
11716        let amount = genesis_config.rent.minimum_balance(0);
11717        let bank1 = Arc::new(Bank::new_for_tests(&genesis_config));
11718        bank1.transfer(amount, &mint_keypair, &pubkey).unwrap();
11719        let result = bank1.get_account_modified_since_parent_with_fixed_root(&pubkey);
11720        assert!(result.is_some());
11721        let (account, slot) = result.unwrap();
11722        assert_eq!(account.lamports(), amount);
11723        assert_eq!(slot, 0);
11724
11725        let bank2 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 1));
11726        assert!(bank2
11727            .get_account_modified_since_parent_with_fixed_root(&pubkey)
11728            .is_none());
11729        bank2.transfer(2 * amount, &mint_keypair, &pubkey).unwrap();
11730        let result = bank1.get_account_modified_since_parent_with_fixed_root(&pubkey);
11731        assert!(result.is_some());
11732        let (account, slot) = result.unwrap();
11733        assert_eq!(account.lamports(), amount);
11734        assert_eq!(slot, 0);
11735        let result = bank2.get_account_modified_since_parent_with_fixed_root(&pubkey);
11736        assert!(result.is_some());
11737        let (account, slot) = result.unwrap();
11738        assert_eq!(account.lamports(), 3 * amount);
11739        assert_eq!(slot, 1);
11740
11741        bank1.squash();
11742
11743        let bank3 = Bank::new_from_parent(&bank2, &Pubkey::default(), 3);
11744        assert_eq!(
11745            None,
11746            bank3.get_account_modified_since_parent_with_fixed_root(&pubkey)
11747        );
11748    }
11749
11750    #[test]
11751    fn test_bank_update_sysvar_account() {
11752        use sysvar::clock::Clock;
11753
11754        let dummy_clock_id = solana_sdk::pubkey::new_rand();
11755        let dummy_rent_epoch = 44;
11756        let (mut genesis_config, _mint_keypair) = create_genesis_config(500);
11757
11758        let expected_previous_slot = 3;
11759        let mut expected_next_slot = expected_previous_slot + 1;
11760
11761        // First, initialize the clock sysvar
11762        activate_all_features(&mut genesis_config);
11763        let bank1 = Arc::new(Bank::new_for_tests(&genesis_config));
11764        assert_eq!(bank1.calculate_capitalization(true), bank1.capitalization());
11765
11766        assert_capitalization_diff(
11767            &bank1,
11768            || {
11769                bank1.update_sysvar_account(&dummy_clock_id, |optional_account| {
11770                    assert!(optional_account.is_none());
11771
11772                    let mut account = create_account(
11773                        &Clock {
11774                            slot: expected_previous_slot,
11775                            ..Clock::default()
11776                        },
11777                        bank1.inherit_specially_retained_account_fields(optional_account),
11778                    );
11779                    account.set_rent_epoch(dummy_rent_epoch);
11780                    account
11781                });
11782                let current_account = bank1.get_account(&dummy_clock_id).unwrap();
11783                assert_eq!(
11784                    expected_previous_slot,
11785                    from_account::<Clock, _>(&current_account).unwrap().slot
11786                );
11787                assert_eq!(dummy_rent_epoch, current_account.rent_epoch());
11788            },
11789            |old, new| {
11790                assert_eq!(
11791                    old + min_rent_excempt_balance_for_sysvars(&bank1, &[sysvar::clock::id()]),
11792                    new
11793                );
11794            },
11795        );
11796
11797        assert_capitalization_diff(
11798            &bank1,
11799            || {
11800                bank1.update_sysvar_account(&dummy_clock_id, |optional_account| {
11801                    assert!(optional_account.is_some());
11802
11803                    create_account(
11804                        &Clock {
11805                            slot: expected_previous_slot,
11806                            ..Clock::default()
11807                        },
11808                        bank1.inherit_specially_retained_account_fields(optional_account),
11809                    )
11810                })
11811            },
11812            |old, new| {
11813                // creating new sysvar twice in a slot shouldn't increment capitalization twice
11814                assert_eq!(old, new);
11815            },
11816        );
11817
11818        // Updating should increment the clock's slot
11819        let bank2 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 1));
11820        assert_capitalization_diff(
11821            &bank2,
11822            || {
11823                bank2.update_sysvar_account(&dummy_clock_id, |optional_account| {
11824                    let slot = from_account::<Clock, _>(optional_account.as_ref().unwrap())
11825                        .unwrap()
11826                        .slot
11827                        + 1;
11828
11829                    create_account(
11830                        &Clock {
11831                            slot,
11832                            ..Clock::default()
11833                        },
11834                        bank2.inherit_specially_retained_account_fields(optional_account),
11835                    )
11836                });
11837                let current_account = bank2.get_account(&dummy_clock_id).unwrap();
11838                assert_eq!(
11839                    expected_next_slot,
11840                    from_account::<Clock, _>(&current_account).unwrap().slot
11841                );
11842                assert_eq!(dummy_rent_epoch, current_account.rent_epoch());
11843            },
11844            |old, new| {
11845                // if existing, capitalization shouldn't change
11846                assert_eq!(old, new);
11847            },
11848        );
11849
11850        // Updating again should give bank2's sysvar to the closure not bank1's.
11851        // Thus, increment expected_next_slot accordingly
11852        expected_next_slot += 1;
11853        assert_capitalization_diff(
11854            &bank2,
11855            || {
11856                bank2.update_sysvar_account(&dummy_clock_id, |optional_account| {
11857                    let slot = from_account::<Clock, _>(optional_account.as_ref().unwrap())
11858                        .unwrap()
11859                        .slot
11860                        + 1;
11861
11862                    create_account(
11863                        &Clock {
11864                            slot,
11865                            ..Clock::default()
11866                        },
11867                        bank2.inherit_specially_retained_account_fields(optional_account),
11868                    )
11869                });
11870                let current_account = bank2.get_account(&dummy_clock_id).unwrap();
11871                assert_eq!(
11872                    expected_next_slot,
11873                    from_account::<Clock, _>(&current_account).unwrap().slot
11874                );
11875            },
11876            |old, new| {
11877                // updating twice in a slot shouldn't increment capitalization twice
11878                assert_eq!(old, new);
11879            },
11880        );
11881    }
11882
11883    #[test]
11884    fn test_bank_epoch_vote_accounts() {
11885        let leader_pubkey = solana_sdk::pubkey::new_rand();
11886        let leader_lamports = 3;
11887        let mut genesis_config =
11888            create_genesis_config_with_leader(5, &leader_pubkey, leader_lamports).genesis_config;
11889
11890        // set this up weird, forces future generation, odd mod(), etc.
11891        //  this says: "vote_accounts for epoch X should be generated at slot index 3 in epoch X-2...
11892        const SLOTS_PER_EPOCH: u64 = MINIMUM_SLOTS_PER_EPOCH as u64;
11893        const LEADER_SCHEDULE_SLOT_OFFSET: u64 = SLOTS_PER_EPOCH * 3 - 3;
11894        // no warmup allows me to do the normal division stuff below
11895        genesis_config.epoch_schedule =
11896            EpochSchedule::custom(SLOTS_PER_EPOCH, LEADER_SCHEDULE_SLOT_OFFSET, false);
11897
11898        let parent = Arc::new(Bank::new_for_tests(&genesis_config));
11899        let mut leader_vote_stake: Vec<_> = parent
11900            .epoch_vote_accounts(0)
11901            .map(|accounts| {
11902                accounts
11903                    .iter()
11904                    .filter_map(|(pubkey, (stake, account))| {
11905                        if let Ok(vote_state) = account.vote_state().as_ref() {
11906                            if vote_state.node_pubkey == leader_pubkey {
11907                                Some((*pubkey, *stake))
11908                            } else {
11909                                None
11910                            }
11911                        } else {
11912                            None
11913                        }
11914                    })
11915                    .collect()
11916            })
11917            .unwrap();
11918        assert_eq!(leader_vote_stake.len(), 1);
11919        let (leader_vote_account, leader_stake) = leader_vote_stake.pop().unwrap();
11920        assert!(leader_stake > 0);
11921
11922        let leader_stake = Stake {
11923            delegation: Delegation {
11924                stake: leader_lamports,
11925                activation_epoch: std::u64::MAX, // bootstrap
11926                ..Delegation::default()
11927            },
11928            ..Stake::default()
11929        };
11930
11931        let mut epoch = 1;
11932        loop {
11933            if epoch > LEADER_SCHEDULE_SLOT_OFFSET / SLOTS_PER_EPOCH {
11934                break;
11935            }
11936            let vote_accounts = parent.epoch_vote_accounts(epoch);
11937            assert!(vote_accounts.is_some());
11938
11939            // epoch_stakes are a snapshot at the leader_schedule_slot_offset boundary
11940            //   in the prior epoch (0 in this case)
11941            assert_eq!(
11942                leader_stake.stake(0, None),
11943                vote_accounts.unwrap().get(&leader_vote_account).unwrap().0
11944            );
11945
11946            epoch += 1;
11947        }
11948
11949        // child crosses epoch boundary and is the first slot in the epoch
11950        let child = Bank::new_from_parent(
11951            &parent,
11952            &leader_pubkey,
11953            SLOTS_PER_EPOCH - (LEADER_SCHEDULE_SLOT_OFFSET % SLOTS_PER_EPOCH),
11954        );
11955
11956        assert!(child.epoch_vote_accounts(epoch).is_some());
11957        assert_eq!(
11958            leader_stake.stake(child.epoch(), None),
11959            child
11960                .epoch_vote_accounts(epoch)
11961                .unwrap()
11962                .get(&leader_vote_account)
11963                .unwrap()
11964                .0
11965        );
11966
11967        // child crosses epoch boundary but isn't the first slot in the epoch, still
11968        //  makes an epoch stakes snapshot at 1
11969        let child = Bank::new_from_parent(
11970            &parent,
11971            &leader_pubkey,
11972            SLOTS_PER_EPOCH - (LEADER_SCHEDULE_SLOT_OFFSET % SLOTS_PER_EPOCH) + 1,
11973        );
11974        assert!(child.epoch_vote_accounts(epoch).is_some());
11975        assert_eq!(
11976            leader_stake.stake(child.epoch(), None),
11977            child
11978                .epoch_vote_accounts(epoch)
11979                .unwrap()
11980                .get(&leader_vote_account)
11981                .unwrap()
11982                .0
11983        );
11984    }
11985
11986    #[test]
11987    fn test_zero_signatures() {
11988        solana_logger::setup();
11989        let (genesis_config, mint_keypair) = create_genesis_config(500);
11990        let mut bank = Bank::new_for_tests(&genesis_config);
11991        bank.fee_rate_governor.lamports_per_signature = 2;
11992        let key = Keypair::new();
11993
11994        let mut transfer_instruction =
11995            system_instruction::transfer(&mint_keypair.pubkey(), &key.pubkey(), 0);
11996        transfer_instruction.accounts[0].is_signer = false;
11997        let message = Message::new(&[transfer_instruction], None);
11998        let tx = Transaction::new(&[&Keypair::new(); 0], message, bank.last_blockhash());
11999
12000        assert_eq!(
12001            bank.process_transaction(&tx),
12002            Err(TransactionError::SanitizeFailure)
12003        );
12004        assert_eq!(bank.get_balance(&key.pubkey()), 0);
12005    }
12006
12007    #[test]
12008    fn test_bank_get_slots_in_epoch() {
12009        let (genesis_config, _) = create_genesis_config(500);
12010
12011        let bank = Bank::new_for_tests(&genesis_config);
12012
12013        assert_eq!(bank.get_slots_in_epoch(0), MINIMUM_SLOTS_PER_EPOCH as u64);
12014        assert_eq!(
12015            bank.get_slots_in_epoch(2),
12016            (MINIMUM_SLOTS_PER_EPOCH * 4) as u64
12017        );
12018        assert_eq!(
12019            bank.get_slots_in_epoch(5000),
12020            genesis_config.epoch_schedule.slots_per_epoch
12021        );
12022    }
12023
12024    #[test]
12025    fn test_is_delta_true() {
12026        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
12027        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12028        let key1 = Keypair::new();
12029        let tx_transfer_mint_to_1 = system_transaction::transfer(
12030            &mint_keypair,
12031            &key1.pubkey(),
12032            genesis_config.rent.minimum_balance(0),
12033            genesis_config.hash(),
12034        );
12035        assert_eq!(bank.process_transaction(&tx_transfer_mint_to_1), Ok(()));
12036        assert!(bank.is_delta.load(Relaxed));
12037
12038        let bank1 = new_from_parent(&bank);
12039        let hash1 = bank1.hash_internal_state();
12040        assert!(!bank1.is_delta.load(Relaxed));
12041        assert_ne!(hash1, bank.hash());
12042        // ticks don't make a bank into a delta or change its state unless a block boundary is crossed
12043        bank1.register_tick(&Hash::default());
12044        assert!(!bank1.is_delta.load(Relaxed));
12045        assert_eq!(bank1.hash_internal_state(), hash1);
12046    }
12047
12048    #[test]
12049    fn test_is_empty() {
12050        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
12051        let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
12052        let key1 = Keypair::new();
12053
12054        // The zeroth bank is empty becasue there are no transactions
12055        assert!(bank0.is_empty());
12056
12057        // Set is_delta to true, bank is no longer empty
12058        let tx_transfer_mint_to_1 = system_transaction::transfer(
12059            &mint_keypair,
12060            &key1.pubkey(),
12061            genesis_config.rent.minimum_balance(0),
12062            genesis_config.hash(),
12063        );
12064        assert_eq!(bank0.process_transaction(&tx_transfer_mint_to_1), Ok(()));
12065        assert!(!bank0.is_empty());
12066    }
12067
12068    #[test]
12069    fn test_bank_inherit_tx_count() {
12070        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
12071        let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
12072
12073        // Bank 1
12074        let bank1 = Arc::new(Bank::new_from_parent(
12075            &bank0,
12076            &solana_sdk::pubkey::new_rand(),
12077            1,
12078        ));
12079        // Bank 2
12080        let bank2 = Bank::new_from_parent(&bank0, &solana_sdk::pubkey::new_rand(), 2);
12081
12082        // transfer a token
12083        assert_eq!(
12084            bank1.process_transaction(&system_transaction::transfer(
12085                &mint_keypair,
12086                &Keypair::new().pubkey(),
12087                genesis_config.rent.minimum_balance(0),
12088                genesis_config.hash(),
12089            )),
12090            Ok(())
12091        );
12092
12093        assert_eq!(bank0.transaction_count(), 0);
12094        assert_eq!(bank2.transaction_count(), 0);
12095        assert_eq!(bank1.transaction_count(), 1);
12096
12097        bank1.squash();
12098
12099        assert_eq!(bank0.transaction_count(), 0);
12100        assert_eq!(bank2.transaction_count(), 0);
12101        assert_eq!(bank1.transaction_count(), 1);
12102
12103        let bank6 = Bank::new_from_parent(&bank1, &solana_sdk::pubkey::new_rand(), 3);
12104        assert_eq!(bank1.transaction_count(), 1);
12105        assert_eq!(bank6.transaction_count(), 1);
12106
12107        bank6.squash();
12108        assert_eq!(bank6.transaction_count(), 1);
12109    }
12110
12111    #[test]
12112    fn test_bank_inherit_fee_rate_governor() {
12113        let (mut genesis_config, _mint_keypair) = create_genesis_config(500);
12114        genesis_config
12115            .fee_rate_governor
12116            .target_lamports_per_signature = 123;
12117
12118        let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
12119        let bank1 = Arc::new(new_from_parent(&bank0));
12120        assert_eq!(
12121            bank0.fee_rate_governor.target_lamports_per_signature / 2,
12122            bank1
12123                .fee_rate_governor
12124                .create_fee_calculator()
12125                .lamports_per_signature
12126        );
12127    }
12128
12129    #[test]
12130    fn test_bank_vote_accounts() {
12131        let GenesisConfigInfo {
12132            genesis_config,
12133            mint_keypair,
12134            ..
12135        } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 1);
12136        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12137
12138        let vote_accounts = bank.vote_accounts();
12139        assert_eq!(vote_accounts.len(), 1); // bootstrap validator has
12140                                            // to have a vote account
12141
12142        let vote_keypair = Keypair::new();
12143        let instructions = vote_instruction::create_account(
12144            &mint_keypair.pubkey(),
12145            &vote_keypair.pubkey(),
12146            &VoteInit {
12147                node_pubkey: mint_keypair.pubkey(),
12148                authorized_voter: vote_keypair.pubkey(),
12149                authorized_withdrawer: vote_keypair.pubkey(),
12150                commission: 0,
12151            },
12152            10,
12153        );
12154
12155        let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
12156        let transaction = Transaction::new(
12157            &[&mint_keypair, &vote_keypair],
12158            message,
12159            bank.last_blockhash(),
12160        );
12161
12162        bank.process_transaction(&transaction).unwrap();
12163
12164        let vote_accounts = bank.vote_accounts();
12165
12166        assert_eq!(vote_accounts.len(), 2);
12167
12168        assert!(vote_accounts.get(&vote_keypair.pubkey()).is_some());
12169
12170        assert!(bank.withdraw(&vote_keypair.pubkey(), 10).is_ok());
12171
12172        let vote_accounts = bank.vote_accounts();
12173
12174        assert_eq!(vote_accounts.len(), 1);
12175    }
12176
12177    #[test]
12178    fn test_bank_cloned_stake_delegations() {
12179        let GenesisConfigInfo {
12180            mut genesis_config,
12181            mint_keypair,
12182            ..
12183        } = create_genesis_config_with_leader(
12184            123_456_000_000_000,
12185            &solana_sdk::pubkey::new_rand(),
12186            123_000_000_000,
12187        );
12188        genesis_config.rent = Rent::default();
12189        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12190
12191        let stake_delegations = bank.stakes_cache.stakes().stake_delegations().clone();
12192        assert_eq!(stake_delegations.len(), 1); // bootstrap validator has
12193                                                // to have a stake delegation
12194
12195        let (vote_balance, stake_balance) = {
12196            let rent = &bank.rent_collector().rent;
12197            let vote_rent_exempt_reserve = rent.minimum_balance(VoteState::size_of());
12198            let stake_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of());
12199            let minimum_delegation =
12200                solana_stake_program::get_minimum_delegation(&bank.feature_set);
12201            (
12202                vote_rent_exempt_reserve,
12203                stake_rent_exempt_reserve + minimum_delegation,
12204            )
12205        };
12206
12207        let vote_keypair = Keypair::new();
12208        let mut instructions = vote_instruction::create_account(
12209            &mint_keypair.pubkey(),
12210            &vote_keypair.pubkey(),
12211            &VoteInit {
12212                node_pubkey: mint_keypair.pubkey(),
12213                authorized_voter: vote_keypair.pubkey(),
12214                authorized_withdrawer: vote_keypair.pubkey(),
12215                commission: 0,
12216            },
12217            vote_balance,
12218        );
12219
12220        let stake_keypair = Keypair::new();
12221        instructions.extend(stake_instruction::create_account_and_delegate_stake(
12222            &mint_keypair.pubkey(),
12223            &stake_keypair.pubkey(),
12224            &vote_keypair.pubkey(),
12225            &Authorized::auto(&stake_keypair.pubkey()),
12226            &Lockup::default(),
12227            stake_balance,
12228        ));
12229
12230        let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
12231        let transaction = Transaction::new(
12232            &[&mint_keypair, &vote_keypair, &stake_keypair],
12233            message,
12234            bank.last_blockhash(),
12235        );
12236
12237        bank.process_transaction(&transaction).unwrap();
12238
12239        let stake_delegations = bank.stakes_cache.stakes().stake_delegations().clone();
12240        assert_eq!(stake_delegations.len(), 2);
12241        assert!(stake_delegations.get(&stake_keypair.pubkey()).is_some());
12242    }
12243
12244    #[allow(deprecated)]
12245    #[test]
12246    fn test_bank_fees_account() {
12247        let (mut genesis_config, _) = create_genesis_config(500);
12248        genesis_config.fee_rate_governor = FeeRateGovernor::new(12345, 0);
12249        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12250
12251        let fees_account = bank.get_account(&sysvar::fees::id()).unwrap();
12252        let fees = from_account::<Fees, _>(&fees_account).unwrap();
12253        assert_eq!(
12254            bank.fee_rate_governor.lamports_per_signature,
12255            fees.fee_calculator.lamports_per_signature
12256        );
12257        assert_eq!(fees.fee_calculator.lamports_per_signature, 12345);
12258    }
12259
12260    #[test]
12261    fn test_is_delta_with_no_committables() {
12262        let (genesis_config, mint_keypair) = create_genesis_config(8000);
12263        let bank = Bank::new_for_tests(&genesis_config);
12264        bank.is_delta.store(false, Relaxed);
12265
12266        let keypair1 = Keypair::new();
12267        let keypair2 = Keypair::new();
12268        let fail_tx =
12269            system_transaction::transfer(&keypair1, &keypair2.pubkey(), 1, bank.last_blockhash());
12270
12271        // Should fail with TransactionError::AccountNotFound, which means
12272        // the account which this tx operated on will not be committed. Thus
12273        // the bank is_delta should still be false
12274        assert_eq!(
12275            bank.process_transaction(&fail_tx),
12276            Err(TransactionError::AccountNotFound)
12277        );
12278
12279        // Check the bank is_delta is still false
12280        assert!(!bank.is_delta.load(Relaxed));
12281
12282        // Should fail with InstructionError, but InstructionErrors are committable,
12283        // so is_delta should be true
12284        assert_eq!(
12285            bank.transfer(10_001, &mint_keypair, &solana_sdk::pubkey::new_rand()),
12286            Err(TransactionError::InstructionError(
12287                0,
12288                SystemError::ResultWithNegativeLamports.into(),
12289            ))
12290        );
12291
12292        assert!(bank.is_delta.load(Relaxed));
12293    }
12294
12295    #[test]
12296    fn test_bank_get_program_accounts() {
12297        let (genesis_config, mint_keypair) = create_genesis_config(500);
12298        let parent = Arc::new(Bank::new_for_tests(&genesis_config));
12299        parent.restore_old_behavior_for_fragile_tests();
12300
12301        let genesis_accounts: Vec<_> = parent.get_all_accounts_with_modified_slots().unwrap();
12302        assert!(
12303            genesis_accounts
12304                .iter()
12305                .any(|(pubkey, _, _)| *pubkey == mint_keypair.pubkey()),
12306            "mint pubkey not found"
12307        );
12308        assert!(
12309            genesis_accounts
12310                .iter()
12311                .any(|(pubkey, _, _)| solana_sdk::sysvar::is_sysvar_id(pubkey)),
12312            "no sysvars found"
12313        );
12314
12315        let bank0 = Arc::new(new_from_parent(&parent));
12316        let pubkey0 = solana_sdk::pubkey::new_rand();
12317        let program_id = Pubkey::from([2; 32]);
12318        let account0 = AccountSharedData::new(1, 0, &program_id);
12319        bank0.store_account(&pubkey0, &account0);
12320
12321        assert_eq!(
12322            bank0.get_program_accounts_modified_since_parent(&program_id),
12323            vec![(pubkey0, account0.clone())]
12324        );
12325
12326        let bank1 = Arc::new(new_from_parent(&bank0));
12327        bank1.squash();
12328        assert_eq!(
12329            bank0
12330                .get_program_accounts(&program_id, &ScanConfig::default(),)
12331                .unwrap(),
12332            vec![(pubkey0, account0.clone())]
12333        );
12334        assert_eq!(
12335            bank1
12336                .get_program_accounts(&program_id, &ScanConfig::default(),)
12337                .unwrap(),
12338            vec![(pubkey0, account0)]
12339        );
12340        assert_eq!(
12341            bank1.get_program_accounts_modified_since_parent(&program_id),
12342            vec![]
12343        );
12344
12345        let bank2 = Arc::new(new_from_parent(&bank1));
12346        let pubkey1 = solana_sdk::pubkey::new_rand();
12347        let account1 = AccountSharedData::new(3, 0, &program_id);
12348        bank2.store_account(&pubkey1, &account1);
12349        // Accounts with 0 lamports should be filtered out by Accounts::load_by_program()
12350        let pubkey2 = solana_sdk::pubkey::new_rand();
12351        let account2 = AccountSharedData::new(0, 0, &program_id);
12352        bank2.store_account(&pubkey2, &account2);
12353
12354        let bank3 = Arc::new(new_from_parent(&bank2));
12355        bank3.squash();
12356        assert_eq!(
12357            bank1
12358                .get_program_accounts(&program_id, &ScanConfig::default(),)
12359                .unwrap()
12360                .len(),
12361            2
12362        );
12363        assert_eq!(
12364            bank3
12365                .get_program_accounts(&program_id, &ScanConfig::default(),)
12366                .unwrap()
12367                .len(),
12368            2
12369        );
12370    }
12371
12372    #[test]
12373    fn test_get_filtered_indexed_accounts_limit_exceeded() {
12374        let (genesis_config, _mint_keypair) = create_genesis_config(500);
12375        let mut account_indexes = AccountSecondaryIndexes::default();
12376        account_indexes.indexes.insert(AccountIndex::ProgramId);
12377        let bank = Arc::new(Bank::new_with_config_for_tests(
12378            &genesis_config,
12379            account_indexes,
12380            false,
12381            AccountShrinkThreshold::default(),
12382        ));
12383
12384        let address = Pubkey::new_unique();
12385        let program_id = Pubkey::new_unique();
12386        let limit = 100;
12387        let account = AccountSharedData::new(1, limit, &program_id);
12388        bank.store_account(&address, &account);
12389
12390        assert!(bank
12391            .get_filtered_indexed_accounts(
12392                &IndexKey::ProgramId(program_id),
12393                |_| true,
12394                &ScanConfig::default(),
12395                Some(limit), // limit here will be exceeded, resulting in aborted scan
12396            )
12397            .is_err());
12398    }
12399
12400    #[test]
12401    fn test_get_filtered_indexed_accounts() {
12402        let (genesis_config, _mint_keypair) = create_genesis_config(500);
12403        let mut account_indexes = AccountSecondaryIndexes::default();
12404        account_indexes.indexes.insert(AccountIndex::ProgramId);
12405        let bank = Arc::new(Bank::new_with_config_for_tests(
12406            &genesis_config,
12407            account_indexes,
12408            false,
12409            AccountShrinkThreshold::default(),
12410        ));
12411
12412        let address = Pubkey::new_unique();
12413        let program_id = Pubkey::new_unique();
12414        let account = AccountSharedData::new(1, 0, &program_id);
12415        bank.store_account(&address, &account);
12416
12417        let indexed_accounts = bank
12418            .get_filtered_indexed_accounts(
12419                &IndexKey::ProgramId(program_id),
12420                |_| true,
12421                &ScanConfig::default(),
12422                None,
12423            )
12424            .unwrap();
12425        assert_eq!(indexed_accounts.len(), 1);
12426        assert_eq!(indexed_accounts[0], (address, account));
12427
12428        // Even though the account is re-stored in the bank (and the index) under a new program id,
12429        // it is still present in the index under the original program id as well. This
12430        // demonstrates the need for a redundant post-processing filter.
12431        let another_program_id = Pubkey::new_unique();
12432        let new_account = AccountSharedData::new(1, 0, &another_program_id);
12433        let bank = Arc::new(new_from_parent(&bank));
12434        bank.store_account(&address, &new_account);
12435        let indexed_accounts = bank
12436            .get_filtered_indexed_accounts(
12437                &IndexKey::ProgramId(program_id),
12438                |_| true,
12439                &ScanConfig::default(),
12440                None,
12441            )
12442            .unwrap();
12443        assert_eq!(indexed_accounts.len(), 1);
12444        assert_eq!(indexed_accounts[0], (address, new_account.clone()));
12445        let indexed_accounts = bank
12446            .get_filtered_indexed_accounts(
12447                &IndexKey::ProgramId(another_program_id),
12448                |_| true,
12449                &ScanConfig::default(),
12450                None,
12451            )
12452            .unwrap();
12453        assert_eq!(indexed_accounts.len(), 1);
12454        assert_eq!(indexed_accounts[0], (address, new_account.clone()));
12455
12456        // Post-processing filter
12457        let indexed_accounts = bank
12458            .get_filtered_indexed_accounts(
12459                &IndexKey::ProgramId(program_id),
12460                |account| account.owner() == &program_id,
12461                &ScanConfig::default(),
12462                None,
12463            )
12464            .unwrap();
12465        assert!(indexed_accounts.is_empty());
12466        let indexed_accounts = bank
12467            .get_filtered_indexed_accounts(
12468                &IndexKey::ProgramId(another_program_id),
12469                |account| account.owner() == &another_program_id,
12470                &ScanConfig::default(),
12471                None,
12472            )
12473            .unwrap();
12474        assert_eq!(indexed_accounts.len(), 1);
12475        assert_eq!(indexed_accounts[0], (address, new_account));
12476    }
12477
12478    #[test]
12479    fn test_status_cache_ancestors() {
12480        solana_logger::setup();
12481        let parent = create_simple_test_arc_bank(500);
12482        let bank1 = Arc::new(new_from_parent(&parent));
12483        let mut bank = bank1;
12484        for _ in 0..MAX_CACHE_ENTRIES * 2 {
12485            bank = Arc::new(new_from_parent(&bank));
12486            bank.squash();
12487        }
12488
12489        let bank = new_from_parent(&bank);
12490        assert_eq!(
12491            bank.status_cache_ancestors(),
12492            (bank.slot() - MAX_CACHE_ENTRIES as u64..=bank.slot()).collect::<Vec<_>>()
12493        );
12494    }
12495
12496    #[test]
12497    fn test_add_builtin() {
12498        let (genesis_config, mint_keypair) = create_genesis_config(500);
12499        let mut bank = Bank::new_for_tests(&genesis_config);
12500
12501        fn mock_vote_program_id() -> Pubkey {
12502            Pubkey::from([42u8; 32])
12503        }
12504        fn mock_vote_processor(
12505            _first_instruction_account: usize,
12506            invoke_context: &mut InvokeContext,
12507        ) -> std::result::Result<(), InstructionError> {
12508            let transaction_context = &invoke_context.transaction_context;
12509            let instruction_context = transaction_context.get_current_instruction_context()?;
12510            let program_id = instruction_context.get_last_program_key(transaction_context)?;
12511            if mock_vote_program_id() != *program_id {
12512                return Err(InstructionError::IncorrectProgramId);
12513            }
12514            Err(InstructionError::Custom(42))
12515        }
12516
12517        assert!(bank.get_account(&mock_vote_program_id()).is_none());
12518        bank.add_builtin(
12519            "mock_vote_program",
12520            &mock_vote_program_id(),
12521            mock_vote_processor,
12522        );
12523        assert!(bank.get_account(&mock_vote_program_id()).is_some());
12524
12525        let mock_account = Keypair::new();
12526        let mock_validator_identity = Keypair::new();
12527        let mut instructions = vote_instruction::create_account(
12528            &mint_keypair.pubkey(),
12529            &mock_account.pubkey(),
12530            &VoteInit {
12531                node_pubkey: mock_validator_identity.pubkey(),
12532                ..VoteInit::default()
12533            },
12534            1,
12535        );
12536        instructions[1].program_id = mock_vote_program_id();
12537
12538        let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
12539        let transaction = Transaction::new(
12540            &[&mint_keypair, &mock_account, &mock_validator_identity],
12541            message,
12542            bank.last_blockhash(),
12543        );
12544
12545        assert_eq!(
12546            bank.process_transaction(&transaction),
12547            Err(TransactionError::InstructionError(
12548                1,
12549                InstructionError::Custom(42)
12550            ))
12551        );
12552    }
12553
12554    #[test]
12555    fn test_add_duplicate_static_program() {
12556        let GenesisConfigInfo {
12557            genesis_config,
12558            mint_keypair,
12559            ..
12560        } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 0);
12561        let mut bank = Bank::new_for_tests(&genesis_config);
12562
12563        fn mock_vote_processor(
12564            _first_instruction_account: usize,
12565            _invoke_context: &mut InvokeContext,
12566        ) -> std::result::Result<(), InstructionError> {
12567            Err(InstructionError::Custom(42))
12568        }
12569
12570        let mock_account = Keypair::new();
12571        let mock_validator_identity = Keypair::new();
12572        let instructions = vote_instruction::create_account(
12573            &mint_keypair.pubkey(),
12574            &mock_account.pubkey(),
12575            &VoteInit {
12576                node_pubkey: mock_validator_identity.pubkey(),
12577                ..VoteInit::default()
12578            },
12579            1,
12580        );
12581
12582        let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
12583        let transaction = Transaction::new(
12584            &[&mint_keypair, &mock_account, &mock_validator_identity],
12585            message,
12586            bank.last_blockhash(),
12587        );
12588
12589        let vote_loader_account = bank.get_account(&solana_vote_program::id()).unwrap();
12590        bank.add_builtin(
12591            "solana_vote_program",
12592            &solana_vote_program::id(),
12593            mock_vote_processor,
12594        );
12595        let new_vote_loader_account = bank.get_account(&solana_vote_program::id()).unwrap();
12596        // Vote loader account should not be updated since it was included in the genesis config.
12597        assert_eq!(vote_loader_account.data(), new_vote_loader_account.data());
12598        assert_eq!(
12599            bank.process_transaction(&transaction),
12600            Err(TransactionError::InstructionError(
12601                1,
12602                InstructionError::Custom(42)
12603            ))
12604        );
12605    }
12606
12607    #[test]
12608    fn test_add_instruction_processor_for_existing_unrelated_accounts() {
12609        let mut bank = create_simple_test_bank(500);
12610
12611        fn mock_ix_processor(
12612            _first_instruction_account: usize,
12613            _invoke_context: &mut InvokeContext,
12614        ) -> std::result::Result<(), InstructionError> {
12615            Err(InstructionError::Custom(42))
12616        }
12617
12618        // Non-builtin loader accounts can not be used for instruction processing
12619        {
12620            let stakes = bank.stakes_cache.stakes();
12621            assert!(stakes.vote_accounts().as_ref().is_empty());
12622        }
12623        assert!(bank.stakes_cache.stakes().stake_delegations().is_empty());
12624        assert_eq!(bank.calculate_capitalization(true), bank.capitalization());
12625
12626        let ((vote_id, vote_account), (stake_id, stake_account)) =
12627            crate::stakes::tests::create_staked_node_accounts(1_0000);
12628        bank.capitalization
12629            .fetch_add(vote_account.lamports() + stake_account.lamports(), Relaxed);
12630        bank.store_account(&vote_id, &vote_account);
12631        bank.store_account(&stake_id, &stake_account);
12632        {
12633            let stakes = bank.stakes_cache.stakes();
12634            assert!(!stakes.vote_accounts().as_ref().is_empty());
12635        }
12636        assert!(!bank.stakes_cache.stakes().stake_delegations().is_empty());
12637        assert_eq!(bank.calculate_capitalization(true), bank.capitalization());
12638
12639        bank.add_builtin("mock_program1", &vote_id, mock_ix_processor);
12640        bank.add_builtin("mock_program2", &stake_id, mock_ix_processor);
12641        {
12642            let stakes = bank.stakes_cache.stakes();
12643            assert!(stakes.vote_accounts().as_ref().is_empty());
12644        }
12645        assert!(bank.stakes_cache.stakes().stake_delegations().is_empty());
12646        assert_eq!(bank.calculate_capitalization(true), bank.capitalization());
12647        assert_eq!(
12648            "mock_program1",
12649            String::from_utf8_lossy(bank.get_account(&vote_id).unwrap_or_default().data())
12650        );
12651        assert_eq!(
12652            "mock_program2",
12653            String::from_utf8_lossy(bank.get_account(&stake_id).unwrap_or_default().data())
12654        );
12655
12656        // Re-adding builtin programs should be no-op
12657        bank.update_accounts_hash();
12658        let old_hash = bank.get_accounts_hash();
12659        bank.add_builtin("mock_program1", &vote_id, mock_ix_processor);
12660        bank.add_builtin("mock_program2", &stake_id, mock_ix_processor);
12661        bank.update_accounts_hash();
12662        let new_hash = bank.get_accounts_hash();
12663        assert_eq!(old_hash, new_hash);
12664        {
12665            let stakes = bank.stakes_cache.stakes();
12666            assert!(stakes.vote_accounts().as_ref().is_empty());
12667        }
12668        assert!(bank.stakes_cache.stakes().stake_delegations().is_empty());
12669        assert_eq!(bank.calculate_capitalization(true), bank.capitalization());
12670        assert_eq!(
12671            "mock_program1",
12672            String::from_utf8_lossy(bank.get_account(&vote_id).unwrap_or_default().data())
12673        );
12674        assert_eq!(
12675            "mock_program2",
12676            String::from_utf8_lossy(bank.get_account(&stake_id).unwrap_or_default().data())
12677        );
12678    }
12679
12680    #[allow(deprecated)]
12681    #[test]
12682    fn test_recent_blockhashes_sysvar() {
12683        let mut bank = create_simple_test_arc_bank(500);
12684        for i in 1..5 {
12685            let bhq_account = bank.get_account(&sysvar::recent_blockhashes::id()).unwrap();
12686            let recent_blockhashes =
12687                from_account::<sysvar::recent_blockhashes::RecentBlockhashes, _>(&bhq_account)
12688                    .unwrap();
12689            // Check length
12690            assert_eq!(recent_blockhashes.len(), i);
12691            let most_recent_hash = recent_blockhashes.iter().next().unwrap().blockhash;
12692            // Check order
12693            assert!(bank.is_hash_valid_for_age(&most_recent_hash, 0));
12694            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
12695            bank = Arc::new(new_from_parent(&bank));
12696        }
12697    }
12698
12699    #[allow(deprecated)]
12700    #[test]
12701    fn test_blockhash_queue_sysvar_consistency() {
12702        let mut bank = create_simple_test_arc_bank(100_000);
12703        goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
12704
12705        let bhq_account = bank.get_account(&sysvar::recent_blockhashes::id()).unwrap();
12706        let recent_blockhashes =
12707            from_account::<sysvar::recent_blockhashes::RecentBlockhashes, _>(&bhq_account).unwrap();
12708
12709        let sysvar_recent_blockhash = recent_blockhashes[0].blockhash;
12710        let bank_last_blockhash = bank.last_blockhash();
12711        assert_eq!(sysvar_recent_blockhash, bank_last_blockhash);
12712    }
12713
12714    #[test]
12715    fn test_hash_internal_state_unchanged() {
12716        let (genesis_config, _) = create_genesis_config(500);
12717        let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
12718        bank0.freeze();
12719        let bank0_hash = bank0.hash();
12720        let bank1 = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
12721        bank1.freeze();
12722        let bank1_hash = bank1.hash();
12723        // Checkpointing should always result in a new state
12724        assert_ne!(bank0_hash, bank1_hash);
12725    }
12726
12727    #[test]
12728    fn test_ticks_change_state() {
12729        let (genesis_config, _) = create_genesis_config(500);
12730        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
12731        let bank1 = new_from_parent(&bank);
12732        let hash1 = bank1.hash_internal_state();
12733        // ticks don't change its state unless a block boundary is crossed
12734        for _ in 0..genesis_config.ticks_per_slot {
12735            assert_eq!(bank1.hash_internal_state(), hash1);
12736            bank1.register_tick(&Hash::default());
12737        }
12738        assert_ne!(bank1.hash_internal_state(), hash1);
12739    }
12740
12741    #[ignore]
12742    #[test]
12743    fn test_banks_leak() {
12744        fn add_lotsa_stake_accounts(genesis_config: &mut GenesisConfig) {
12745            const LOTSA: usize = 4_096;
12746
12747            (0..LOTSA).for_each(|_| {
12748                let pubkey = solana_sdk::pubkey::new_rand();
12749                genesis_config.add_account(
12750                    pubkey,
12751                    stake_state::create_lockup_stake_account(
12752                        &Authorized::auto(&pubkey),
12753                        &Lockup::default(),
12754                        &Rent::default(),
12755                        50_000_000,
12756                    ),
12757                );
12758            });
12759        }
12760        solana_logger::setup();
12761        let (mut genesis_config, _) = create_genesis_config(100_000_000_000_000);
12762        add_lotsa_stake_accounts(&mut genesis_config);
12763        let mut bank = std::sync::Arc::new(Bank::new_for_tests(&genesis_config));
12764        let mut num_banks = 0;
12765        let pid = std::process::id();
12766        #[cfg(not(target_os = "linux"))]
12767        error!(
12768            "\nYou can run this to watch RAM:\n   while read -p 'banks: '; do echo $(( $(ps -o vsize= -p {})/$REPLY));done", pid
12769        );
12770        loop {
12771            num_banks += 1;
12772            bank = std::sync::Arc::new(new_from_parent(&bank));
12773            if num_banks % 100 == 0 {
12774                #[cfg(target_os = "linux")]
12775                {
12776                    let pages_consumed = std::fs::read_to_string(format!("/proc/{}/statm", pid))
12777                        .unwrap()
12778                        .split_whitespace()
12779                        .next()
12780                        .unwrap()
12781                        .parse::<usize>()
12782                        .unwrap();
12783                    error!(
12784                        "at {} banks: {} mem or {}kB/bank",
12785                        num_banks,
12786                        pages_consumed * 4096,
12787                        (pages_consumed * 4) / num_banks
12788                    );
12789                }
12790                #[cfg(not(target_os = "linux"))]
12791                {
12792                    error!("{} banks, sleeping for 5 sec", num_banks);
12793                    std::thread::sleep(Duration::new(5, 0));
12794                }
12795            }
12796        }
12797    }
12798
12799    fn get_nonce_blockhash(bank: &Bank, nonce_pubkey: &Pubkey) -> Option<Hash> {
12800        let account = bank.get_account(nonce_pubkey)?;
12801        let nonce_versions = StateMut::<nonce::state::Versions>::state(&account);
12802        match nonce_versions.ok()?.state() {
12803            nonce::State::Initialized(ref data) => Some(data.blockhash()),
12804            _ => None,
12805        }
12806    }
12807
12808    fn nonce_setup(
12809        bank: &mut Arc<Bank>,
12810        mint_keypair: &Keypair,
12811        custodian_lamports: u64,
12812        nonce_lamports: u64,
12813        nonce_authority: Option<Pubkey>,
12814    ) -> Result<(Keypair, Keypair)> {
12815        let custodian_keypair = Keypair::new();
12816        let nonce_keypair = Keypair::new();
12817        /* Setup accounts */
12818        let mut setup_ixs = vec![system_instruction::transfer(
12819            &mint_keypair.pubkey(),
12820            &custodian_keypair.pubkey(),
12821            custodian_lamports,
12822        )];
12823        let nonce_authority = nonce_authority.unwrap_or_else(|| nonce_keypair.pubkey());
12824        setup_ixs.extend_from_slice(&system_instruction::create_nonce_account(
12825            &custodian_keypair.pubkey(),
12826            &nonce_keypair.pubkey(),
12827            &nonce_authority,
12828            nonce_lamports,
12829        ));
12830        let message = Message::new(&setup_ixs, Some(&mint_keypair.pubkey()));
12831        let setup_tx = Transaction::new(
12832            &[mint_keypair, &custodian_keypair, &nonce_keypair],
12833            message,
12834            bank.last_blockhash(),
12835        );
12836        bank.process_transaction(&setup_tx)?;
12837        Ok((custodian_keypair, nonce_keypair))
12838    }
12839
12840    fn setup_nonce_with_bank<F>(
12841        supply_lamports: u64,
12842        mut genesis_cfg_fn: F,
12843        custodian_lamports: u64,
12844        nonce_lamports: u64,
12845        nonce_authority: Option<Pubkey>,
12846        feature_set: FeatureSet,
12847    ) -> Result<(Arc<Bank>, Keypair, Keypair, Keypair)>
12848    where
12849        F: FnMut(&mut GenesisConfig),
12850    {
12851        let (mut genesis_config, mint_keypair) = create_genesis_config(supply_lamports);
12852        genesis_config.rent.lamports_per_byte_year = 0;
12853        genesis_cfg_fn(&mut genesis_config);
12854        let mut bank = Bank::new_for_tests(&genesis_config);
12855        bank.feature_set = Arc::new(feature_set);
12856        let mut bank = Arc::new(bank);
12857
12858        // Banks 0 and 1 have no fees, wait two blocks before
12859        // initializing our nonce accounts
12860        for _ in 0..2 {
12861            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
12862            bank = Arc::new(new_from_parent(&bank));
12863        }
12864
12865        let (custodian_keypair, nonce_keypair) = nonce_setup(
12866            &mut bank,
12867            &mint_keypair,
12868            custodian_lamports,
12869            nonce_lamports,
12870            nonce_authority,
12871        )?;
12872
12873        // The setup nonce is not valid to be used until the next bank
12874        // so wait one more block
12875        goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
12876        bank = Arc::new(new_from_parent(&bank));
12877
12878        Ok((bank, mint_keypair, custodian_keypair, nonce_keypair))
12879    }
12880
12881    impl Bank {
12882        fn next_durable_nonce(&self) -> DurableNonce {
12883            let hash_queue = self.blockhash_queue.read().unwrap();
12884            let last_blockhash = hash_queue.last_hash();
12885            DurableNonce::from_blockhash(&last_blockhash)
12886        }
12887    }
12888
12889    #[test]
12890    fn test_check_transaction_for_nonce_ok() {
12891        let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
12892            10_000_000,
12893            |_| {},
12894            5_000_000,
12895            250_000,
12896            None,
12897            FeatureSet::all_enabled(),
12898        )
12899        .unwrap();
12900        let custodian_pubkey = custodian_keypair.pubkey();
12901        let nonce_pubkey = nonce_keypair.pubkey();
12902
12903        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
12904        let tx = Transaction::new_signed_with_payer(
12905            &[
12906                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
12907                system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
12908            ],
12909            Some(&custodian_pubkey),
12910            &[&custodian_keypair, &nonce_keypair],
12911            nonce_hash,
12912        );
12913        let nonce_account = bank.get_account(&nonce_pubkey).unwrap();
12914        assert_eq!(
12915            bank.check_transaction_for_nonce(
12916                &SanitizedTransaction::from_transaction_for_tests(tx),
12917                &bank.next_durable_nonce(),
12918            ),
12919            Some((nonce_pubkey, nonce_account))
12920        );
12921    }
12922
12923    #[test]
12924    fn test_check_transaction_for_nonce_not_nonce_fail() {
12925        let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
12926            10_000_000,
12927            |_| {},
12928            5_000_000,
12929            250_000,
12930            None,
12931            FeatureSet::all_enabled(),
12932        )
12933        .unwrap();
12934        let custodian_pubkey = custodian_keypair.pubkey();
12935        let nonce_pubkey = nonce_keypair.pubkey();
12936
12937        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
12938        let tx = Transaction::new_signed_with_payer(
12939            &[
12940                system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
12941                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
12942            ],
12943            Some(&custodian_pubkey),
12944            &[&custodian_keypair, &nonce_keypair],
12945            nonce_hash,
12946        );
12947        assert!(bank
12948            .check_transaction_for_nonce(
12949                &SanitizedTransaction::from_transaction_for_tests(tx,),
12950                &bank.next_durable_nonce(),
12951            )
12952            .is_none());
12953    }
12954
12955    #[test]
12956    fn test_check_transaction_for_nonce_missing_ix_pubkey_fail() {
12957        let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
12958            10_000_000,
12959            |_| {},
12960            5_000_000,
12961            250_000,
12962            None,
12963            FeatureSet::all_enabled(),
12964        )
12965        .unwrap();
12966        let custodian_pubkey = custodian_keypair.pubkey();
12967        let nonce_pubkey = nonce_keypair.pubkey();
12968
12969        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
12970        let mut tx = Transaction::new_signed_with_payer(
12971            &[
12972                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
12973                system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
12974            ],
12975            Some(&custodian_pubkey),
12976            &[&custodian_keypair, &nonce_keypair],
12977            nonce_hash,
12978        );
12979        tx.message.instructions[0].accounts.clear();
12980        assert!(bank
12981            .check_transaction_for_nonce(
12982                &SanitizedTransaction::from_transaction_for_tests(tx),
12983                &bank.next_durable_nonce(),
12984            )
12985            .is_none());
12986    }
12987
12988    #[test]
12989    fn test_check_transaction_for_nonce_nonce_acc_does_not_exist_fail() {
12990        let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
12991            10_000_000,
12992            |_| {},
12993            5_000_000,
12994            250_000,
12995            None,
12996            FeatureSet::all_enabled(),
12997        )
12998        .unwrap();
12999        let custodian_pubkey = custodian_keypair.pubkey();
13000        let nonce_pubkey = nonce_keypair.pubkey();
13001        let missing_keypair = Keypair::new();
13002        let missing_pubkey = missing_keypair.pubkey();
13003
13004        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13005        let tx = Transaction::new_signed_with_payer(
13006            &[
13007                system_instruction::advance_nonce_account(&missing_pubkey, &nonce_pubkey),
13008                system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
13009            ],
13010            Some(&custodian_pubkey),
13011            &[&custodian_keypair, &nonce_keypair],
13012            nonce_hash,
13013        );
13014        assert!(bank
13015            .check_transaction_for_nonce(
13016                &SanitizedTransaction::from_transaction_for_tests(tx),
13017                &bank.next_durable_nonce(),
13018            )
13019            .is_none());
13020    }
13021
13022    #[test]
13023    fn test_check_transaction_for_nonce_bad_tx_hash_fail() {
13024        let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13025            10_000_000,
13026            |_| {},
13027            5_000_000,
13028            250_000,
13029            None,
13030            FeatureSet::all_enabled(),
13031        )
13032        .unwrap();
13033        let custodian_pubkey = custodian_keypair.pubkey();
13034        let nonce_pubkey = nonce_keypair.pubkey();
13035
13036        let tx = Transaction::new_signed_with_payer(
13037            &[
13038                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13039                system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
13040            ],
13041            Some(&custodian_pubkey),
13042            &[&custodian_keypair, &nonce_keypair],
13043            Hash::default(),
13044        );
13045        assert!(bank
13046            .check_transaction_for_nonce(
13047                &SanitizedTransaction::from_transaction_for_tests(tx),
13048                &bank.next_durable_nonce(),
13049            )
13050            .is_none());
13051    }
13052
13053    #[test]
13054    fn test_assign_from_nonce_account_fail() {
13055        let bank = create_simple_test_arc_bank(100_000_000);
13056        let nonce = Keypair::new();
13057        let nonce_account = AccountSharedData::new_data(
13058            42_424_242,
13059            &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data::default())),
13060            &system_program::id(),
13061        )
13062        .unwrap();
13063        let blockhash = bank.last_blockhash();
13064        bank.store_account(&nonce.pubkey(), &nonce_account);
13065
13066        let ix = system_instruction::assign(&nonce.pubkey(), &Pubkey::from([9u8; 32]));
13067        let message = Message::new(&[ix], Some(&nonce.pubkey()));
13068        let tx = Transaction::new(&[&nonce], message, blockhash);
13069
13070        let expect = Err(TransactionError::InstructionError(
13071            0,
13072            InstructionError::ModifiedProgramId,
13073        ));
13074        assert_eq!(bank.process_transaction(&tx), expect);
13075    }
13076
13077    #[test]
13078    fn test_nonce_must_be_advanceable() {
13079        let mut bank = create_simple_test_bank(100_000_000);
13080        bank.feature_set = Arc::new(FeatureSet::all_enabled());
13081        let bank = Arc::new(bank);
13082        let nonce_keypair = Keypair::new();
13083        let nonce_authority = nonce_keypair.pubkey();
13084        let durable_nonce = DurableNonce::from_blockhash(&bank.last_blockhash());
13085        let nonce_account = AccountSharedData::new_data(
13086            42_424_242,
13087            &nonce::state::Versions::new(nonce::State::Initialized(nonce::state::Data::new(
13088                nonce_authority,
13089                durable_nonce,
13090                5000,
13091            ))),
13092            &system_program::id(),
13093        )
13094        .unwrap();
13095        bank.store_account(&nonce_keypair.pubkey(), &nonce_account);
13096
13097        let ix =
13098            system_instruction::advance_nonce_account(&nonce_keypair.pubkey(), &nonce_authority);
13099        let message = Message::new(&[ix], Some(&nonce_keypair.pubkey()));
13100        let tx = Transaction::new(&[&nonce_keypair], message, *durable_nonce.as_hash());
13101        assert_eq!(
13102            bank.process_transaction(&tx),
13103            Err(TransactionError::BlockhashNotFound)
13104        );
13105    }
13106
13107    #[test]
13108    fn test_nonce_transaction() {
13109        let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13110            10_000_000,
13111            |_| {},
13112            5_000_000,
13113            250_000,
13114            None,
13115            FeatureSet::all_enabled(),
13116        )
13117        .unwrap();
13118        let alice_keypair = Keypair::new();
13119        let alice_pubkey = alice_keypair.pubkey();
13120        let custodian_pubkey = custodian_keypair.pubkey();
13121        let nonce_pubkey = nonce_keypair.pubkey();
13122
13123        assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000);
13124        assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
13125
13126        /* Grab the hash stored in the nonce account */
13127        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13128
13129        /* Kick nonce hash off the blockhash_queue */
13130        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13131            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13132            bank = Arc::new(new_from_parent(&bank));
13133        }
13134
13135        /* Expect a non-Nonce transfer to fail */
13136        assert_eq!(
13137            bank.process_transaction(&system_transaction::transfer(
13138                &custodian_keypair,
13139                &alice_pubkey,
13140                100_000,
13141                nonce_hash
13142            ),),
13143            Err(TransactionError::BlockhashNotFound),
13144        );
13145        /* Check fee not charged */
13146        assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000);
13147
13148        /* Nonce transfer */
13149        let nonce_tx = Transaction::new_signed_with_payer(
13150            &[
13151                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13152                system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
13153            ],
13154            Some(&custodian_pubkey),
13155            &[&custodian_keypair, &nonce_keypair],
13156            nonce_hash,
13157        );
13158        assert_eq!(bank.process_transaction(&nonce_tx), Ok(()));
13159
13160        /* Check balances */
13161        let mut recent_message = nonce_tx.message;
13162        recent_message.recent_blockhash = bank.last_blockhash();
13163        let mut expected_balance = 4_650_000
13164            - bank
13165                .get_fee_for_message(&recent_message.try_into().unwrap())
13166                .unwrap();
13167        assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13168        assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
13169        assert_eq!(bank.get_balance(&alice_pubkey), 100_000);
13170
13171        /* Confirm stored nonce has advanced */
13172        let new_nonce = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13173        assert_ne!(nonce_hash, new_nonce);
13174
13175        /* Nonce re-use fails */
13176        let nonce_tx = Transaction::new_signed_with_payer(
13177            &[
13178                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13179                system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
13180            ],
13181            Some(&custodian_pubkey),
13182            &[&custodian_keypair, &nonce_keypair],
13183            nonce_hash,
13184        );
13185        assert_eq!(
13186            bank.process_transaction(&nonce_tx),
13187            Err(TransactionError::BlockhashNotFound)
13188        );
13189        /* Check fee not charged and nonce not advanced */
13190        assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13191        assert_eq!(
13192            new_nonce,
13193            get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13194        );
13195
13196        let nonce_hash = new_nonce;
13197
13198        /* Kick nonce hash off the blockhash_queue */
13199        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13200            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13201            bank = Arc::new(new_from_parent(&bank));
13202        }
13203
13204        let nonce_tx = Transaction::new_signed_with_payer(
13205            &[
13206                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13207                system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
13208            ],
13209            Some(&custodian_pubkey),
13210            &[&custodian_keypair, &nonce_keypair],
13211            nonce_hash,
13212        );
13213        assert_eq!(
13214            bank.process_transaction(&nonce_tx),
13215            Err(TransactionError::InstructionError(
13216                1,
13217                system_instruction::SystemError::ResultWithNegativeLamports.into(),
13218            ))
13219        );
13220        /* Check fee charged and nonce has advanced */
13221        let mut recent_message = nonce_tx.message.clone();
13222        recent_message.recent_blockhash = bank.last_blockhash();
13223        expected_balance -= bank
13224            .get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap())
13225            .unwrap();
13226        assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13227        assert_ne!(
13228            nonce_hash,
13229            get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13230        );
13231        /* Confirm replaying a TX that failed with InstructionError::* now
13232         * fails with TransactionError::BlockhashNotFound
13233         */
13234        assert_eq!(
13235            bank.process_transaction(&nonce_tx),
13236            Err(TransactionError::BlockhashNotFound),
13237        );
13238    }
13239
13240    #[test]
13241    fn test_nonce_transaction_with_tx_wide_caps() {
13242        let feature_set = FeatureSet::all_enabled();
13243        let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) =
13244            setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None, feature_set)
13245                .unwrap();
13246        let alice_keypair = Keypair::new();
13247        let alice_pubkey = alice_keypair.pubkey();
13248        let custodian_pubkey = custodian_keypair.pubkey();
13249        let nonce_pubkey = nonce_keypair.pubkey();
13250
13251        assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000);
13252        assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
13253
13254        /* Grab the hash stored in the nonce account */
13255        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13256
13257        /* Kick nonce hash off the blockhash_queue */
13258        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13259            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13260            bank = Arc::new(new_from_parent(&bank));
13261        }
13262
13263        /* Expect a non-Nonce transfer to fail */
13264        assert_eq!(
13265            bank.process_transaction(&system_transaction::transfer(
13266                &custodian_keypair,
13267                &alice_pubkey,
13268                100_000,
13269                nonce_hash
13270            ),),
13271            Err(TransactionError::BlockhashNotFound),
13272        );
13273        /* Check fee not charged */
13274        assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000);
13275
13276        /* Nonce transfer */
13277        let nonce_tx = Transaction::new_signed_with_payer(
13278            &[
13279                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13280                system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
13281            ],
13282            Some(&custodian_pubkey),
13283            &[&custodian_keypair, &nonce_keypair],
13284            nonce_hash,
13285        );
13286        assert_eq!(bank.process_transaction(&nonce_tx), Ok(()));
13287
13288        /* Check balances */
13289        let mut recent_message = nonce_tx.message;
13290        recent_message.recent_blockhash = bank.last_blockhash();
13291        let mut expected_balance = 4_650_000
13292            - bank
13293                .get_fee_for_message(&recent_message.try_into().unwrap())
13294                .unwrap();
13295        assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13296        assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
13297        assert_eq!(bank.get_balance(&alice_pubkey), 100_000);
13298
13299        /* Confirm stored nonce has advanced */
13300        let new_nonce = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13301        assert_ne!(nonce_hash, new_nonce);
13302
13303        /* Nonce re-use fails */
13304        let nonce_tx = Transaction::new_signed_with_payer(
13305            &[
13306                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13307                system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
13308            ],
13309            Some(&custodian_pubkey),
13310            &[&custodian_keypair, &nonce_keypair],
13311            nonce_hash,
13312        );
13313        assert_eq!(
13314            bank.process_transaction(&nonce_tx),
13315            Err(TransactionError::BlockhashNotFound)
13316        );
13317        /* Check fee not charged and nonce not advanced */
13318        assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13319        assert_eq!(
13320            new_nonce,
13321            get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13322        );
13323
13324        let nonce_hash = new_nonce;
13325
13326        /* Kick nonce hash off the blockhash_queue */
13327        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13328            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13329            bank = Arc::new(new_from_parent(&bank));
13330        }
13331
13332        let nonce_tx = Transaction::new_signed_with_payer(
13333            &[
13334                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13335                system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
13336            ],
13337            Some(&custodian_pubkey),
13338            &[&custodian_keypair, &nonce_keypair],
13339            nonce_hash,
13340        );
13341        assert_eq!(
13342            bank.process_transaction(&nonce_tx),
13343            Err(TransactionError::InstructionError(
13344                1,
13345                system_instruction::SystemError::ResultWithNegativeLamports.into(),
13346            ))
13347        );
13348        /* Check fee charged and nonce has advanced */
13349        let mut recent_message = nonce_tx.message.clone();
13350        recent_message.recent_blockhash = bank.last_blockhash();
13351        expected_balance -= bank
13352            .get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap())
13353            .unwrap();
13354        assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance);
13355        assert_ne!(
13356            nonce_hash,
13357            get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13358        );
13359        /* Confirm replaying a TX that failed with InstructionError::* now
13360         * fails with TransactionError::BlockhashNotFound
13361         */
13362        assert_eq!(
13363            bank.process_transaction(&nonce_tx),
13364            Err(TransactionError::BlockhashNotFound),
13365        );
13366    }
13367
13368    #[test]
13369    fn test_nonce_authority() {
13370        solana_logger::setup();
13371        let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13372            10_000_000,
13373            |_| {},
13374            5_000_000,
13375            250_000,
13376            None,
13377            FeatureSet::all_enabled(),
13378        )
13379        .unwrap();
13380        let alice_keypair = Keypair::new();
13381        let alice_pubkey = alice_keypair.pubkey();
13382        let custodian_pubkey = custodian_keypair.pubkey();
13383        let nonce_pubkey = nonce_keypair.pubkey();
13384        let bad_nonce_authority_keypair = Keypair::new();
13385        let bad_nonce_authority = bad_nonce_authority_keypair.pubkey();
13386        let custodian_account = bank.get_account(&custodian_pubkey).unwrap();
13387
13388        debug!("alice: {}", alice_pubkey);
13389        debug!("custodian: {}", custodian_pubkey);
13390        debug!("nonce: {}", nonce_pubkey);
13391        debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey));
13392        debug!("cust: {:?}", custodian_account);
13393        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13394
13395        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13396            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13397            bank = Arc::new(new_from_parent(&bank));
13398        }
13399
13400        let nonce_tx = Transaction::new_signed_with_payer(
13401            &[
13402                system_instruction::advance_nonce_account(&nonce_pubkey, &bad_nonce_authority),
13403                system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 42),
13404            ],
13405            Some(&custodian_pubkey),
13406            &[&custodian_keypair, &bad_nonce_authority_keypair],
13407            nonce_hash,
13408        );
13409        debug!("{:?}", nonce_tx);
13410        let initial_custodian_balance = custodian_account.lamports();
13411        assert_eq!(
13412            bank.process_transaction(&nonce_tx),
13413            Err(TransactionError::BlockhashNotFound),
13414        );
13415        /* Check fee was *not* charged and nonce has *not* advanced */
13416        let mut recent_message = nonce_tx.message;
13417        recent_message.recent_blockhash = bank.last_blockhash();
13418        assert_eq!(
13419            bank.get_balance(&custodian_pubkey),
13420            initial_custodian_balance
13421        );
13422        assert_eq!(
13423            nonce_hash,
13424            get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13425        );
13426    }
13427
13428    #[test]
13429    fn test_nonce_payer() {
13430        solana_logger::setup();
13431        let nonce_starting_balance = 250_000;
13432        let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13433            10_000_000,
13434            |_| {},
13435            5_000_000,
13436            nonce_starting_balance,
13437            None,
13438            FeatureSet::all_enabled(),
13439        )
13440        .unwrap();
13441        let alice_keypair = Keypair::new();
13442        let alice_pubkey = alice_keypair.pubkey();
13443        let custodian_pubkey = custodian_keypair.pubkey();
13444        let nonce_pubkey = nonce_keypair.pubkey();
13445
13446        debug!("alice: {}", alice_pubkey);
13447        debug!("custodian: {}", custodian_pubkey);
13448        debug!("nonce: {}", nonce_pubkey);
13449        debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey));
13450        debug!("cust: {:?}", bank.get_account(&custodian_pubkey));
13451        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13452
13453        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13454            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13455            bank = Arc::new(new_from_parent(&bank));
13456        }
13457
13458        let nonce_tx = Transaction::new_signed_with_payer(
13459            &[
13460                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13461                system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
13462            ],
13463            Some(&nonce_pubkey),
13464            &[&custodian_keypair, &nonce_keypair],
13465            nonce_hash,
13466        );
13467        debug!("{:?}", nonce_tx);
13468        assert_eq!(
13469            bank.process_transaction(&nonce_tx),
13470            Err(TransactionError::InstructionError(
13471                1,
13472                system_instruction::SystemError::ResultWithNegativeLamports.into(),
13473            ))
13474        );
13475        /* Check fee charged and nonce has advanced */
13476        let mut recent_message = nonce_tx.message;
13477        recent_message.recent_blockhash = bank.last_blockhash();
13478        assert_eq!(
13479            bank.get_balance(&nonce_pubkey),
13480            nonce_starting_balance
13481                - bank
13482                    .get_fee_for_message(&recent_message.try_into().unwrap())
13483                    .unwrap()
13484        );
13485        assert_ne!(
13486            nonce_hash,
13487            get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13488        );
13489    }
13490
13491    #[test]
13492    fn test_nonce_payer_tx_wide_cap() {
13493        solana_logger::setup();
13494        let nonce_starting_balance =
13495            250_000 + FeeStructure::default().compute_fee_bins.last().unwrap().fee;
13496        let feature_set = FeatureSet::all_enabled();
13497        let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13498            10_000_000,
13499            |_| {},
13500            5_000_000,
13501            nonce_starting_balance,
13502            None,
13503            feature_set,
13504        )
13505        .unwrap();
13506        let alice_keypair = Keypair::new();
13507        let alice_pubkey = alice_keypair.pubkey();
13508        let custodian_pubkey = custodian_keypair.pubkey();
13509        let nonce_pubkey = nonce_keypair.pubkey();
13510
13511        debug!("alice: {}", alice_pubkey);
13512        debug!("custodian: {}", custodian_pubkey);
13513        debug!("nonce: {}", nonce_pubkey);
13514        debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey));
13515        debug!("cust: {:?}", bank.get_account(&custodian_pubkey));
13516        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13517
13518        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13519            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13520            bank = Arc::new(new_from_parent(&bank));
13521        }
13522
13523        let nonce_tx = Transaction::new_signed_with_payer(
13524            &[
13525                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13526                system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
13527            ],
13528            Some(&nonce_pubkey),
13529            &[&custodian_keypair, &nonce_keypair],
13530            nonce_hash,
13531        );
13532        debug!("{:?}", nonce_tx);
13533
13534        assert_eq!(
13535            bank.process_transaction(&nonce_tx),
13536            Err(TransactionError::InstructionError(
13537                1,
13538                system_instruction::SystemError::ResultWithNegativeLamports.into(),
13539            ))
13540        );
13541        /* Check fee charged and nonce has advanced */
13542        let mut recent_message = nonce_tx.message;
13543        recent_message.recent_blockhash = bank.last_blockhash();
13544        assert_eq!(
13545            bank.get_balance(&nonce_pubkey),
13546            nonce_starting_balance
13547                - bank
13548                    .get_fee_for_message(&recent_message.try_into().unwrap())
13549                    .unwrap()
13550        );
13551        assert_ne!(
13552            nonce_hash,
13553            get_nonce_blockhash(&bank, &nonce_pubkey).unwrap()
13554        );
13555    }
13556
13557    #[test]
13558    fn test_nonce_fee_calculator_updates() {
13559        let (mut genesis_config, mint_keypair) = create_genesis_config(1_000_000);
13560        genesis_config.rent.lamports_per_byte_year = 0;
13561        let mut bank = Bank::new_for_tests(&genesis_config);
13562        bank.feature_set = Arc::new(FeatureSet::all_enabled());
13563        let mut bank = Arc::new(bank);
13564
13565        // Deliberately use bank 0 to initialize nonce account, so that nonce account fee_calculator indicates 0 fees
13566        let (custodian_keypair, nonce_keypair) =
13567            nonce_setup(&mut bank, &mint_keypair, 500_000, 100_000, None).unwrap();
13568        let custodian_pubkey = custodian_keypair.pubkey();
13569        let nonce_pubkey = nonce_keypair.pubkey();
13570
13571        // Grab the hash and fee_calculator stored in the nonce account
13572        let (stored_nonce_hash, stored_fee_calculator) = bank
13573            .get_account(&nonce_pubkey)
13574            .and_then(|acc| {
13575                let nonce_versions = StateMut::<nonce::state::Versions>::state(&acc);
13576                match nonce_versions.ok()?.state() {
13577                    nonce::State::Initialized(ref data) => {
13578                        Some((data.blockhash(), data.fee_calculator))
13579                    }
13580                    _ => None,
13581                }
13582            })
13583            .unwrap();
13584
13585        // Kick nonce hash off the blockhash_queue
13586        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13587            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13588            bank = Arc::new(new_from_parent(&bank));
13589        }
13590
13591        // Nonce transfer
13592        let nonce_tx = Transaction::new_signed_with_payer(
13593            &[
13594                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13595                system_instruction::transfer(
13596                    &custodian_pubkey,
13597                    &solana_sdk::pubkey::new_rand(),
13598                    100_000,
13599                ),
13600            ],
13601            Some(&custodian_pubkey),
13602            &[&custodian_keypair, &nonce_keypair],
13603            stored_nonce_hash,
13604        );
13605        bank.process_transaction(&nonce_tx).unwrap();
13606
13607        // Grab the new hash and fee_calculator; both should be updated
13608        let (nonce_hash, fee_calculator) = bank
13609            .get_account(&nonce_pubkey)
13610            .and_then(|acc| {
13611                let nonce_versions = StateMut::<nonce::state::Versions>::state(&acc);
13612                match nonce_versions.ok()?.state() {
13613                    nonce::State::Initialized(ref data) => {
13614                        Some((data.blockhash(), data.fee_calculator))
13615                    }
13616                    _ => None,
13617                }
13618            })
13619            .unwrap();
13620
13621        assert_ne!(stored_nonce_hash, nonce_hash);
13622        assert_ne!(stored_fee_calculator, fee_calculator);
13623    }
13624
13625    #[test]
13626    fn test_nonce_fee_calculator_updates_tx_wide_cap() {
13627        let (mut genesis_config, mint_keypair) = create_genesis_config(1_000_000);
13628        genesis_config.rent.lamports_per_byte_year = 0;
13629        let mut bank = Bank::new_for_tests(&genesis_config);
13630        bank.feature_set = Arc::new(FeatureSet::all_enabled());
13631        let mut bank = Arc::new(bank);
13632
13633        // Deliberately use bank 0 to initialize nonce account, so that nonce account fee_calculator indicates 0 fees
13634        let (custodian_keypair, nonce_keypair) =
13635            nonce_setup(&mut bank, &mint_keypair, 500_000, 100_000, None).unwrap();
13636        let custodian_pubkey = custodian_keypair.pubkey();
13637        let nonce_pubkey = nonce_keypair.pubkey();
13638
13639        // Grab the hash and fee_calculator stored in the nonce account
13640        let (stored_nonce_hash, stored_fee_calculator) = bank
13641            .get_account(&nonce_pubkey)
13642            .and_then(|acc| {
13643                let nonce_versions = StateMut::<nonce::state::Versions>::state(&acc);
13644                match nonce_versions.ok()?.state() {
13645                    nonce::State::Initialized(ref data) => {
13646                        Some((data.blockhash(), data.fee_calculator))
13647                    }
13648                    _ => None,
13649                }
13650            })
13651            .unwrap();
13652
13653        // Kick nonce hash off the blockhash_queue
13654        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13655            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13656            bank = Arc::new(new_from_parent(&bank));
13657        }
13658
13659        // Nonce transfer
13660        let nonce_tx = Transaction::new_signed_with_payer(
13661            &[
13662                system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
13663                system_instruction::transfer(
13664                    &custodian_pubkey,
13665                    &solana_sdk::pubkey::new_rand(),
13666                    100_000,
13667                ),
13668            ],
13669            Some(&custodian_pubkey),
13670            &[&custodian_keypair, &nonce_keypair],
13671            stored_nonce_hash,
13672        );
13673        bank.process_transaction(&nonce_tx).unwrap();
13674
13675        // Grab the new hash and fee_calculator; both should be updated
13676        let (nonce_hash, fee_calculator) = bank
13677            .get_account(&nonce_pubkey)
13678            .and_then(|acc| {
13679                let nonce_versions = StateMut::<nonce::state::Versions>::state(&acc);
13680                match nonce_versions.ok()?.state() {
13681                    nonce::State::Initialized(ref data) => {
13682                        Some((data.blockhash(), data.fee_calculator))
13683                    }
13684                    _ => None,
13685                }
13686            })
13687            .unwrap();
13688
13689        assert_ne!(stored_nonce_hash, nonce_hash);
13690        assert_ne!(stored_fee_calculator, fee_calculator);
13691    }
13692
13693    #[test]
13694    fn test_check_ro_durable_nonce_fails() {
13695        let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(
13696            10_000_000,
13697            |_| {},
13698            5_000_000,
13699            250_000,
13700            None,
13701            FeatureSet::all_enabled(),
13702        )
13703        .unwrap();
13704        let custodian_pubkey = custodian_keypair.pubkey();
13705        let nonce_pubkey = nonce_keypair.pubkey();
13706
13707        let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap();
13708        let account_metas = vec![
13709            AccountMeta::new_readonly(nonce_pubkey, false),
13710            #[allow(deprecated)]
13711            AccountMeta::new_readonly(sysvar::recent_blockhashes::id(), false),
13712            AccountMeta::new_readonly(nonce_pubkey, true),
13713        ];
13714        let nonce_instruction = Instruction::new_with_bincode(
13715            system_program::id(),
13716            &system_instruction::SystemInstruction::AdvanceNonceAccount,
13717            account_metas,
13718        );
13719        let tx = Transaction::new_signed_with_payer(
13720            &[nonce_instruction],
13721            Some(&custodian_pubkey),
13722            &[&custodian_keypair, &nonce_keypair],
13723            nonce_hash,
13724        );
13725        // SanitizedMessage::get_durable_nonce returns None because nonce
13726        // account is not writable. Durable nonce and blockhash domains are
13727        // separate, so the recent_blockhash (== durable nonce) in the
13728        // transaction is not found in the hash queue.
13729        assert_eq!(
13730            bank.process_transaction(&tx),
13731            Err(TransactionError::BlockhashNotFound),
13732        );
13733        // Kick nonce hash off the blockhash_queue
13734        for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
13735            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
13736            bank = Arc::new(new_from_parent(&bank));
13737        }
13738        // Caught by the runtime because it is a nonce transaction
13739        assert_eq!(
13740            bank.process_transaction(&tx),
13741            Err(TransactionError::BlockhashNotFound)
13742        );
13743        assert_eq!(
13744            bank.check_transaction_for_nonce(
13745                &SanitizedTransaction::from_transaction_for_tests(tx),
13746                &bank.next_durable_nonce(),
13747            ),
13748            None
13749        );
13750    }
13751
13752    #[test]
13753    fn test_collect_balances() {
13754        let parent = create_simple_test_arc_bank(500);
13755        let bank0 = Arc::new(new_from_parent(&parent));
13756
13757        let keypair = Keypair::new();
13758        let pubkey0 = solana_sdk::pubkey::new_rand();
13759        let pubkey1 = solana_sdk::pubkey::new_rand();
13760        let program_id = Pubkey::from([2; 32]);
13761        let keypair_account = AccountSharedData::new(8, 0, &program_id);
13762        let account0 = AccountSharedData::new(11, 0, &program_id);
13763        let program_account = AccountSharedData::new(1, 10, &Pubkey::default());
13764        bank0.store_account(&keypair.pubkey(), &keypair_account);
13765        bank0.store_account(&pubkey0, &account0);
13766        bank0.store_account(&program_id, &program_account);
13767
13768        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
13769        let tx0 = Transaction::new_with_compiled_instructions(
13770            &[&keypair],
13771            &[pubkey0],
13772            Hash::default(),
13773            vec![program_id],
13774            instructions,
13775        );
13776        let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
13777        let tx1 = Transaction::new_with_compiled_instructions(
13778            &[&keypair],
13779            &[pubkey1],
13780            Hash::default(),
13781            vec![program_id],
13782            instructions,
13783        );
13784        let txs = vec![tx0, tx1];
13785        let batch = bank0.prepare_batch_for_tests(txs.clone());
13786        let balances = bank0.collect_balances(&batch);
13787        assert_eq!(balances.len(), 2);
13788        assert_eq!(balances[0], vec![8, 11, 1]);
13789        assert_eq!(balances[1], vec![8, 0, 1]);
13790
13791        let txs: Vec<_> = txs.into_iter().rev().collect();
13792        let batch = bank0.prepare_batch_for_tests(txs);
13793        let balances = bank0.collect_balances(&batch);
13794        assert_eq!(balances.len(), 2);
13795        assert_eq!(balances[0], vec![8, 0, 1]);
13796        assert_eq!(balances[1], vec![8, 11, 1]);
13797    }
13798
13799    #[test]
13800    fn test_pre_post_transaction_balances() {
13801        let (mut genesis_config, _mint_keypair) = create_genesis_config(500_000);
13802        let fee_rate_governor = FeeRateGovernor::new(5000, 0);
13803        genesis_config.fee_rate_governor = fee_rate_governor;
13804        let parent = Arc::new(Bank::new_for_tests(&genesis_config));
13805        let bank0 = Arc::new(new_from_parent(&parent));
13806
13807        let keypair0 = Keypair::new();
13808        let keypair1 = Keypair::new();
13809        let pubkey0 = solana_sdk::pubkey::new_rand();
13810        let pubkey1 = solana_sdk::pubkey::new_rand();
13811        let pubkey2 = solana_sdk::pubkey::new_rand();
13812        let keypair0_account = AccountSharedData::new(8_000, 0, &Pubkey::default());
13813        let keypair1_account = AccountSharedData::new(9_000, 0, &Pubkey::default());
13814        let account0 = AccountSharedData::new(11_000, 0, &Pubkey::default());
13815        bank0.store_account(&keypair0.pubkey(), &keypair0_account);
13816        bank0.store_account(&keypair1.pubkey(), &keypair1_account);
13817        bank0.store_account(&pubkey0, &account0);
13818
13819        let blockhash = bank0.last_blockhash();
13820
13821        let tx0 = system_transaction::transfer(&keypair0, &pubkey0, 2_000, blockhash);
13822        let tx1 = system_transaction::transfer(&Keypair::new(), &pubkey1, 2_000, blockhash);
13823        let tx2 = system_transaction::transfer(&keypair1, &pubkey2, 12_000, blockhash);
13824        let txs = vec![tx0, tx1, tx2];
13825
13826        let lock_result = bank0.prepare_batch_for_tests(txs);
13827        let (transaction_results, transaction_balances_set) = bank0
13828            .load_execute_and_commit_transactions(
13829                &lock_result,
13830                MAX_PROCESSING_AGE,
13831                true,
13832                false,
13833                false,
13834                false,
13835                &mut ExecuteTimings::default(),
13836                None,
13837            );
13838
13839        assert_eq!(transaction_balances_set.pre_balances.len(), 3);
13840        assert_eq!(transaction_balances_set.post_balances.len(), 3);
13841
13842        assert!(transaction_results.execution_results[0].was_executed_successfully());
13843        assert_eq!(
13844            transaction_balances_set.pre_balances[0],
13845            vec![8_000, 11_000, 1]
13846        );
13847        assert_eq!(
13848            transaction_balances_set.post_balances[0],
13849            vec![1_000, 13_000, 1]
13850        );
13851
13852        // Failed transactions still produce balance sets
13853        // This is a TransactionError - not possible to charge fees
13854        assert!(matches!(
13855            transaction_results.execution_results[1],
13856            TransactionExecutionResult::NotExecuted(TransactionError::AccountNotFound),
13857        ));
13858        assert_eq!(transaction_balances_set.pre_balances[1], vec![0, 0, 1]);
13859        assert_eq!(transaction_balances_set.post_balances[1], vec![0, 0, 1]);
13860
13861        // Failed transactions still produce balance sets
13862        // This is an InstructionError - fees charged
13863        assert!(matches!(
13864            transaction_results.execution_results[2],
13865            TransactionExecutionResult::Executed {
13866                details: TransactionExecutionDetails {
13867                    status: Err(TransactionError::InstructionError(
13868                        0,
13869                        InstructionError::Custom(1),
13870                    )),
13871                    ..
13872                },
13873                ..
13874            },
13875        ));
13876        assert_eq!(transaction_balances_set.pre_balances[2], vec![9_000, 0, 1]);
13877        assert_eq!(transaction_balances_set.post_balances[2], vec![4_000, 0, 1]);
13878    }
13879
13880    #[test]
13881    fn test_transaction_with_duplicate_accounts_in_instruction() {
13882        let (genesis_config, mint_keypair) = create_genesis_config(500);
13883        let mut bank = Bank::new_for_tests(&genesis_config);
13884
13885        fn mock_process_instruction(
13886            _first_instruction_account: usize,
13887            invoke_context: &mut InvokeContext,
13888        ) -> result::Result<(), InstructionError> {
13889            let transaction_context = &invoke_context.transaction_context;
13890            let instruction_context = transaction_context.get_current_instruction_context()?;
13891            let instruction_data = instruction_context.get_instruction_data();
13892            let lamports = u64::from_le_bytes(instruction_data.try_into().unwrap());
13893            instruction_context
13894                .try_borrow_instruction_account(transaction_context, 2)?
13895                .checked_sub_lamports(lamports)?;
13896            instruction_context
13897                .try_borrow_instruction_account(transaction_context, 1)?
13898                .checked_add_lamports(lamports)?;
13899            instruction_context
13900                .try_borrow_instruction_account(transaction_context, 0)?
13901                .checked_sub_lamports(lamports)?;
13902            instruction_context
13903                .try_borrow_instruction_account(transaction_context, 1)?
13904                .checked_add_lamports(lamports)?;
13905            Ok(())
13906        }
13907
13908        let mock_program_id = Pubkey::from([2u8; 32]);
13909        bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
13910
13911        let from_pubkey = solana_sdk::pubkey::new_rand();
13912        let to_pubkey = solana_sdk::pubkey::new_rand();
13913        let dup_pubkey = from_pubkey;
13914        let from_account = AccountSharedData::new(sol_to_lamports(100.), 1, &mock_program_id);
13915        let to_account = AccountSharedData::new(0, 1, &mock_program_id);
13916        bank.store_account(&from_pubkey, &from_account);
13917        bank.store_account(&to_pubkey, &to_account);
13918
13919        let account_metas = vec![
13920            AccountMeta::new(from_pubkey, false),
13921            AccountMeta::new(to_pubkey, false),
13922            AccountMeta::new(dup_pubkey, false),
13923        ];
13924        let instruction =
13925            Instruction::new_with_bincode(mock_program_id, &sol_to_lamports(10.), account_metas);
13926        let tx = Transaction::new_signed_with_payer(
13927            &[instruction],
13928            Some(&mint_keypair.pubkey()),
13929            &[&mint_keypair],
13930            bank.last_blockhash(),
13931        );
13932
13933        let result = bank.process_transaction(&tx);
13934        assert_eq!(result, Ok(()));
13935        assert_eq!(bank.get_balance(&from_pubkey), sol_to_lamports(80.));
13936        assert_eq!(bank.get_balance(&to_pubkey), sol_to_lamports(20.));
13937    }
13938
13939    #[test]
13940    fn test_transaction_with_program_ids_passed_to_programs() {
13941        let (genesis_config, mint_keypair) = create_genesis_config(500);
13942        let mut bank = Bank::new_for_tests(&genesis_config);
13943
13944        #[allow(clippy::unnecessary_wraps)]
13945        fn mock_process_instruction(
13946            _first_instruction_account: usize,
13947            _invoke_context: &mut InvokeContext,
13948        ) -> result::Result<(), InstructionError> {
13949            Ok(())
13950        }
13951
13952        let mock_program_id = Pubkey::from([2u8; 32]);
13953        bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
13954
13955        let from_pubkey = solana_sdk::pubkey::new_rand();
13956        let to_pubkey = solana_sdk::pubkey::new_rand();
13957        let dup_pubkey = from_pubkey;
13958        let from_account = AccountSharedData::new(100, 1, &mock_program_id);
13959        let to_account = AccountSharedData::new(0, 1, &mock_program_id);
13960        bank.store_account(&from_pubkey, &from_account);
13961        bank.store_account(&to_pubkey, &to_account);
13962
13963        let account_metas = vec![
13964            AccountMeta::new(from_pubkey, false),
13965            AccountMeta::new(to_pubkey, false),
13966            AccountMeta::new(dup_pubkey, false),
13967            AccountMeta::new(mock_program_id, false),
13968        ];
13969        let instruction = Instruction::new_with_bincode(mock_program_id, &10, account_metas);
13970        let tx = Transaction::new_signed_with_payer(
13971            &[instruction],
13972            Some(&mint_keypair.pubkey()),
13973            &[&mint_keypair],
13974            bank.last_blockhash(),
13975        );
13976
13977        let result = bank.process_transaction(&tx);
13978        assert_eq!(result, Ok(()));
13979    }
13980
13981    #[test]
13982    fn test_account_ids_after_program_ids() {
13983        solana_logger::setup();
13984        let (genesis_config, mint_keypair) = create_genesis_config(500);
13985        let mut bank = Bank::new_for_tests(&genesis_config);
13986
13987        let from_pubkey = solana_sdk::pubkey::new_rand();
13988        let to_pubkey = solana_sdk::pubkey::new_rand();
13989
13990        let account_metas = vec![
13991            AccountMeta::new(from_pubkey, false),
13992            AccountMeta::new(to_pubkey, false),
13993        ];
13994
13995        let instruction =
13996            Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
13997        let mut tx = Transaction::new_signed_with_payer(
13998            &[instruction],
13999            Some(&mint_keypair.pubkey()),
14000            &[&mint_keypair],
14001            bank.last_blockhash(),
14002        );
14003
14004        tx.message.account_keys.push(solana_sdk::pubkey::new_rand());
14005
14006        bank.add_builtin(
14007            "mock_vote",
14008            &solana_vote_program::id(),
14009            mock_ok_vote_processor,
14010        );
14011        let result = bank.process_transaction(&tx);
14012        assert_eq!(result, Ok(()));
14013        let account = bank.get_account(&solana_vote_program::id()).unwrap();
14014        info!("account: {:?}", account);
14015        assert!(account.executable());
14016    }
14017
14018    #[test]
14019    fn test_incinerator() {
14020        let (genesis_config, mint_keypair) = create_genesis_config(1_000_000_000_000);
14021        let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
14022
14023        // Move to the first normal slot so normal rent behaviour applies
14024        let bank = Bank::new_from_parent(
14025            &bank0,
14026            &Pubkey::default(),
14027            genesis_config.epoch_schedule.first_normal_slot,
14028        );
14029        let pre_capitalization = bank.capitalization();
14030
14031        // Burn a non-rent exempt amount
14032        let burn_amount = bank.get_minimum_balance_for_rent_exemption(0) - 1;
14033
14034        assert_eq!(bank.get_balance(&incinerator::id()), 0);
14035        bank.transfer(burn_amount, &mint_keypair, &incinerator::id())
14036            .unwrap();
14037        assert_eq!(bank.get_balance(&incinerator::id()), burn_amount);
14038        bank.freeze();
14039        assert_eq!(bank.get_balance(&incinerator::id()), 0);
14040
14041        // Ensure that no rent was collected, and the entire burn amount was removed from bank
14042        // capitalization
14043        assert_eq!(bank.capitalization(), pre_capitalization - burn_amount);
14044    }
14045
14046    #[test]
14047    fn test_duplicate_account_key() {
14048        solana_logger::setup();
14049        let (genesis_config, mint_keypair) = create_genesis_config(500);
14050        let mut bank = Bank::new_for_tests(&genesis_config);
14051
14052        let from_pubkey = solana_sdk::pubkey::new_rand();
14053        let to_pubkey = solana_sdk::pubkey::new_rand();
14054
14055        let account_metas = vec![
14056            AccountMeta::new(from_pubkey, false),
14057            AccountMeta::new(to_pubkey, false),
14058        ];
14059
14060        bank.add_builtin(
14061            "mock_vote",
14062            &solana_vote_program::id(),
14063            mock_ok_vote_processor,
14064        );
14065
14066        let instruction =
14067            Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
14068        let mut tx = Transaction::new_signed_with_payer(
14069            &[instruction],
14070            Some(&mint_keypair.pubkey()),
14071            &[&mint_keypair],
14072            bank.last_blockhash(),
14073        );
14074        tx.message.account_keys.push(from_pubkey);
14075
14076        let result = bank.process_transaction(&tx);
14077        assert_eq!(result, Err(TransactionError::AccountLoadedTwice));
14078    }
14079
14080    #[test]
14081    fn test_process_transaction_with_too_many_account_locks() {
14082        solana_logger::setup();
14083        let (genesis_config, mint_keypair) = create_genesis_config(500);
14084        let mut bank = Bank::new_for_tests(&genesis_config);
14085
14086        let from_pubkey = solana_sdk::pubkey::new_rand();
14087        let to_pubkey = solana_sdk::pubkey::new_rand();
14088
14089        let account_metas = vec![
14090            AccountMeta::new(from_pubkey, false),
14091            AccountMeta::new(to_pubkey, false),
14092        ];
14093
14094        bank.add_builtin(
14095            "mock_vote",
14096            &solana_vote_program::id(),
14097            mock_ok_vote_processor,
14098        );
14099
14100        let instruction =
14101            Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
14102        let mut tx = Transaction::new_signed_with_payer(
14103            &[instruction],
14104            Some(&mint_keypair.pubkey()),
14105            &[&mint_keypair],
14106            bank.last_blockhash(),
14107        );
14108
14109        let transaction_account_lock_limit = bank.get_transaction_account_lock_limit();
14110        while tx.message.account_keys.len() <= transaction_account_lock_limit {
14111            tx.message.account_keys.push(solana_sdk::pubkey::new_rand());
14112        }
14113
14114        let result = bank.process_transaction(&tx);
14115        assert_eq!(result, Err(TransactionError::TooManyAccountLocks));
14116    }
14117
14118    #[test]
14119    fn test_program_id_as_payer() {
14120        solana_logger::setup();
14121        let (genesis_config, mint_keypair) = create_genesis_config(500);
14122        let mut bank = Bank::new_for_tests(&genesis_config);
14123
14124        let from_pubkey = solana_sdk::pubkey::new_rand();
14125        let to_pubkey = solana_sdk::pubkey::new_rand();
14126
14127        let account_metas = vec![
14128            AccountMeta::new(from_pubkey, false),
14129            AccountMeta::new(to_pubkey, false),
14130        ];
14131
14132        bank.add_builtin(
14133            "mock_vote",
14134            &solana_vote_program::id(),
14135            mock_ok_vote_processor,
14136        );
14137
14138        let instruction =
14139            Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
14140        let mut tx = Transaction::new_signed_with_payer(
14141            &[instruction],
14142            Some(&mint_keypair.pubkey()),
14143            &[&mint_keypair],
14144            bank.last_blockhash(),
14145        );
14146
14147        info!(
14148            "mint: {} account keys: {:?}",
14149            mint_keypair.pubkey(),
14150            tx.message.account_keys
14151        );
14152        assert_eq!(tx.message.account_keys.len(), 4);
14153        tx.message.account_keys.clear();
14154        tx.message.account_keys.push(solana_vote_program::id());
14155        tx.message.account_keys.push(mint_keypair.pubkey());
14156        tx.message.account_keys.push(from_pubkey);
14157        tx.message.account_keys.push(to_pubkey);
14158        tx.message.instructions[0].program_id_index = 0;
14159        tx.message.instructions[0].accounts.clear();
14160        tx.message.instructions[0].accounts.push(2);
14161        tx.message.instructions[0].accounts.push(3);
14162
14163        let result = bank.process_transaction(&tx);
14164        assert_eq!(result, Err(TransactionError::SanitizeFailure));
14165    }
14166
14167    #[allow(clippy::unnecessary_wraps)]
14168    fn mock_ok_vote_processor(
14169        _first_instruction_account: usize,
14170        _invoke_context: &mut InvokeContext,
14171    ) -> std::result::Result<(), InstructionError> {
14172        Ok(())
14173    }
14174
14175    #[test]
14176    fn test_ref_account_key_after_program_id() {
14177        let (genesis_config, mint_keypair) = create_genesis_config(500);
14178        let mut bank = Bank::new_for_tests(&genesis_config);
14179
14180        let from_pubkey = solana_sdk::pubkey::new_rand();
14181        let to_pubkey = solana_sdk::pubkey::new_rand();
14182
14183        let account_metas = vec![
14184            AccountMeta::new(from_pubkey, false),
14185            AccountMeta::new(to_pubkey, false),
14186        ];
14187
14188        bank.add_builtin(
14189            "mock_vote",
14190            &solana_vote_program::id(),
14191            mock_ok_vote_processor,
14192        );
14193
14194        let instruction =
14195            Instruction::new_with_bincode(solana_vote_program::id(), &10, account_metas);
14196        let mut tx = Transaction::new_signed_with_payer(
14197            &[instruction],
14198            Some(&mint_keypair.pubkey()),
14199            &[&mint_keypair],
14200            bank.last_blockhash(),
14201        );
14202
14203        tx.message.account_keys.push(solana_sdk::pubkey::new_rand());
14204        assert_eq!(tx.message.account_keys.len(), 5);
14205        tx.message.instructions[0].accounts.remove(0);
14206        tx.message.instructions[0].accounts.push(4);
14207
14208        let result = bank.process_transaction(&tx);
14209        assert_eq!(result, Ok(()));
14210    }
14211
14212    #[test]
14213    fn test_fuzz_instructions() {
14214        solana_logger::setup();
14215        use rand::{thread_rng, Rng};
14216        let mut bank = create_simple_test_bank(1_000_000_000);
14217
14218        let max_programs = 5;
14219        let program_keys: Vec<_> = (0..max_programs)
14220            .enumerate()
14221            .map(|i| {
14222                let key = solana_sdk::pubkey::new_rand();
14223                let name = format!("program{:?}", i);
14224                bank.add_builtin(&name, &key, mock_ok_vote_processor);
14225                (key, name.as_bytes().to_vec())
14226            })
14227            .collect();
14228        let max_keys = 100;
14229        let keys: Vec<_> = (0..max_keys)
14230            .enumerate()
14231            .map(|_| {
14232                let key = solana_sdk::pubkey::new_rand();
14233                let balance = if thread_rng().gen_ratio(9, 10) {
14234                    let lamports = if thread_rng().gen_ratio(1, 5) {
14235                        thread_rng().gen_range(0, 10)
14236                    } else {
14237                        thread_rng().gen_range(20, 100)
14238                    };
14239                    let space = thread_rng().gen_range(0, 10);
14240                    let owner = Pubkey::default();
14241                    let account = AccountSharedData::new(lamports, space, &owner);
14242                    bank.store_account(&key, &account);
14243                    lamports
14244                } else {
14245                    0
14246                };
14247                (key, balance)
14248            })
14249            .collect();
14250        let mut results = HashMap::new();
14251        for _ in 0..2_000 {
14252            let num_keys = if thread_rng().gen_ratio(1, 5) {
14253                thread_rng().gen_range(0, max_keys)
14254            } else {
14255                thread_rng().gen_range(1, 4)
14256            };
14257            let num_instructions = thread_rng().gen_range(0, max_keys - num_keys);
14258
14259            let mut account_keys: Vec<_> = if thread_rng().gen_ratio(1, 5) {
14260                (0..num_keys)
14261                    .map(|_| {
14262                        let idx = thread_rng().gen_range(0, keys.len());
14263                        keys[idx].0
14264                    })
14265                    .collect()
14266            } else {
14267                let mut inserted = HashSet::new();
14268                (0..num_keys)
14269                    .map(|_| {
14270                        let mut idx;
14271                        loop {
14272                            idx = thread_rng().gen_range(0, keys.len());
14273                            if !inserted.contains(&idx) {
14274                                break;
14275                            }
14276                        }
14277                        inserted.insert(idx);
14278                        keys[idx].0
14279                    })
14280                    .collect()
14281            };
14282
14283            let instructions: Vec<_> = if num_keys > 0 {
14284                (0..num_instructions)
14285                    .map(|_| {
14286                        let num_accounts_to_pass = thread_rng().gen_range(0, num_keys);
14287                        let account_indexes = (0..num_accounts_to_pass)
14288                            .map(|_| thread_rng().gen_range(0, num_keys))
14289                            .collect();
14290                        let program_index: u8 = thread_rng().gen_range(0, num_keys) as u8;
14291                        if thread_rng().gen_ratio(4, 5) {
14292                            let programs_index = thread_rng().gen_range(0, program_keys.len());
14293                            account_keys[program_index as usize] = program_keys[programs_index].0;
14294                        }
14295                        CompiledInstruction::new(program_index, &10, account_indexes)
14296                    })
14297                    .collect()
14298            } else {
14299                vec![]
14300            };
14301
14302            let account_keys_len = std::cmp::max(account_keys.len(), 2);
14303            let num_signatures = if thread_rng().gen_ratio(1, 5) {
14304                thread_rng().gen_range(0, account_keys_len + 10)
14305            } else {
14306                thread_rng().gen_range(1, account_keys_len)
14307            };
14308
14309            let num_required_signatures = if thread_rng().gen_ratio(1, 5) {
14310                thread_rng().gen_range(0, account_keys_len + 10) as u8
14311            } else {
14312                thread_rng().gen_range(1, std::cmp::max(2, num_signatures)) as u8
14313            };
14314            let num_readonly_signed_accounts = if thread_rng().gen_ratio(1, 5) {
14315                thread_rng().gen_range(0, account_keys_len) as u8
14316            } else {
14317                let max = if num_required_signatures > 1 {
14318                    num_required_signatures - 1
14319                } else {
14320                    1
14321                };
14322                thread_rng().gen_range(0, max) as u8
14323            };
14324
14325            let num_readonly_unsigned_accounts = if thread_rng().gen_ratio(1, 5)
14326                || (num_required_signatures as usize) >= account_keys_len
14327            {
14328                thread_rng().gen_range(0, account_keys_len) as u8
14329            } else {
14330                thread_rng().gen_range(0, account_keys_len - num_required_signatures as usize) as u8
14331            };
14332
14333            let header = MessageHeader {
14334                num_required_signatures,
14335                num_readonly_signed_accounts,
14336                num_readonly_unsigned_accounts,
14337            };
14338            let message = Message {
14339                header,
14340                account_keys,
14341                recent_blockhash: bank.last_blockhash(),
14342                instructions,
14343            };
14344
14345            let tx = Transaction {
14346                signatures: vec![Signature::default(); num_signatures],
14347                message,
14348            };
14349
14350            let result = bank.process_transaction(&tx);
14351            for (key, balance) in &keys {
14352                assert_eq!(bank.get_balance(key), *balance);
14353            }
14354            for (key, name) in &program_keys {
14355                let account = bank.get_account(key).unwrap();
14356                assert!(account.executable());
14357                assert_eq!(account.data(), name);
14358            }
14359            info!("result: {:?}", result);
14360            let result_key = format!("{:?}", result);
14361            *results.entry(result_key).or_insert(0) += 1;
14362        }
14363        info!("results: {:?}", results);
14364    }
14365
14366    #[test]
14367    fn test_bank_hash_consistency() {
14368        solana_logger::setup();
14369
14370        let mut genesis_config = GenesisConfig::new(
14371            &[(
14372                Pubkey::from([42; 32]),
14373                AccountSharedData::new(1_000_000_000_000, 0, &system_program::id()),
14374            )],
14375            &[],
14376        );
14377        genesis_config.creation_time = 0;
14378        genesis_config.cluster_type = ClusterType::MainnetBeta;
14379        genesis_config.rent.burn_percent = 100;
14380        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
14381        // Check a few slots, cross an epoch boundary
14382        assert_eq!(bank.get_slots_in_epoch(0), 32);
14383        loop {
14384            goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
14385            if bank.slot == 0 {
14386                assert_eq!(
14387                    bank.hash().to_string(),
14388                    "9tLrxkBoNE7zEUZ2g72ZwE4fTfhUQnhC8A4Xt4EmYhP1"
14389                );
14390            }
14391            if bank.slot == 32 {
14392                assert_eq!(
14393                    bank.hash().to_string(),
14394                    "AxphC8xDj9gmFosor5gyiovNvPVMydJCFRUTxn2wFiQf"
14395                );
14396            }
14397            if bank.slot == 64 {
14398                assert_eq!(
14399                    bank.hash().to_string(),
14400                    "4vZCSbBuL8xjE43rCy9Cm3dCh1BMj45heMiMb6n6qgzA"
14401                );
14402            }
14403            if bank.slot == 128 {
14404                assert_eq!(
14405                    bank.hash().to_string(),
14406                    "46LUpeBdJuisnfwgYisvh4x7jnxzBaLfHF614GtcTs59"
14407                );
14408                break;
14409            }
14410            bank = Arc::new(new_from_parent(&bank));
14411        }
14412    }
14413
14414    #[test]
14415    fn test_same_program_id_uses_unqiue_executable_accounts() {
14416        fn nested_processor(
14417            _first_instruction_account: usize,
14418            invoke_context: &mut InvokeContext,
14419        ) -> result::Result<(), InstructionError> {
14420            let transaction_context = &invoke_context.transaction_context;
14421            let instruction_context = transaction_context.get_current_instruction_context()?;
14422            let _ = instruction_context
14423                .try_borrow_program_account(transaction_context, 1)?
14424                .checked_add_lamports(1);
14425            Ok(())
14426        }
14427
14428        let (genesis_config, mint_keypair) = create_genesis_config(50000);
14429        let mut bank = Bank::new_for_tests(&genesis_config);
14430
14431        // Add a new program
14432        let program1_pubkey = solana_sdk::pubkey::new_rand();
14433        bank.add_builtin("program", &program1_pubkey, nested_processor);
14434
14435        // Add a new program owned by the first
14436        let program2_pubkey = solana_sdk::pubkey::new_rand();
14437        let mut program2_account = AccountSharedData::new(42, 1, &program1_pubkey);
14438        program2_account.set_executable(true);
14439        bank.store_account(&program2_pubkey, &program2_account);
14440
14441        let instruction = Instruction::new_with_bincode(program2_pubkey, &10, vec![]);
14442        let tx = Transaction::new_signed_with_payer(
14443            &[instruction.clone(), instruction],
14444            Some(&mint_keypair.pubkey()),
14445            &[&mint_keypair],
14446            bank.last_blockhash(),
14447        );
14448        assert!(bank.process_transaction(&tx).is_ok());
14449        assert_eq!(1, bank.get_balance(&program1_pubkey));
14450        assert_eq!(42, bank.get_balance(&program2_pubkey));
14451    }
14452
14453    fn get_shrink_account_size() -> usize {
14454        let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000_000);
14455
14456        // Set root for bank 0, with caching disabled so we can get the size
14457        // of the storage for this slot
14458        let mut bank0 = Arc::new(Bank::new_with_config_for_tests(
14459            &genesis_config,
14460            AccountSecondaryIndexes::default(),
14461            false,
14462            AccountShrinkThreshold::default(),
14463        ));
14464        bank0.restore_old_behavior_for_fragile_tests();
14465        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank0).unwrap());
14466        bank0.freeze();
14467        bank0.squash();
14468
14469        let sizes = bank0
14470            .rc
14471            .accounts
14472            .scan_slot(0, |stored_account| Some(stored_account.stored_size()));
14473
14474        // Create an account such that it takes DEFAULT_ACCOUNTS_SHRINK_RATIO of the total account space for
14475        // the slot, so when it gets pruned, the storage entry will become a shrink candidate.
14476        let bank0_total_size: usize = sizes.into_iter().sum();
14477        let pubkey0_size = (bank0_total_size as f64 / (1.0 - DEFAULT_ACCOUNTS_SHRINK_RATIO)).ceil();
14478        assert!(
14479            pubkey0_size / (pubkey0_size + bank0_total_size as f64) > DEFAULT_ACCOUNTS_SHRINK_RATIO
14480        );
14481        pubkey0_size as usize
14482    }
14483
14484    #[test]
14485    fn test_clean_nonrooted() {
14486        solana_logger::setup();
14487
14488        let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000_000);
14489        let pubkey0 = Pubkey::from([0; 32]);
14490        let pubkey1 = Pubkey::from([1; 32]);
14491
14492        info!("pubkey0: {}", pubkey0);
14493        info!("pubkey1: {}", pubkey1);
14494
14495        // Set root for bank 0, with caching enabled
14496        let mut bank0 = Arc::new(Bank::new_with_config_for_tests(
14497            &genesis_config,
14498            AccountSecondaryIndexes::default(),
14499            true,
14500            AccountShrinkThreshold::default(),
14501        ));
14502
14503        let account_zero = AccountSharedData::new(0, 0, &Pubkey::new_unique());
14504
14505        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank0).unwrap());
14506        bank0.freeze();
14507        bank0.squash();
14508        // Flush now so that accounts cache cleaning doesn't clean up bank 0 when later
14509        // slots add updates to the cache
14510        bank0.force_flush_accounts_cache();
14511
14512        // Store some lamports in bank 1
14513        let some_lamports = 123;
14514        let mut bank1 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 1));
14515        bank1.deposit(&pubkey0, some_lamports).unwrap();
14516        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank1).unwrap());
14517        bank1.freeze();
14518        bank1.flush_accounts_cache_slot();
14519
14520        bank1.print_accounts_stats();
14521
14522        // Store some lamports for pubkey1 in bank 2, root bank 2
14523        // bank2's parent is bank0
14524        let mut bank2 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 2));
14525        bank2.deposit(&pubkey1, some_lamports).unwrap();
14526        bank2.store_account(&pubkey0, &account_zero);
14527        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank2).unwrap());
14528        bank2.freeze();
14529        bank2.squash();
14530        bank2.force_flush_accounts_cache();
14531
14532        bank2.print_accounts_stats();
14533        drop(bank1);
14534
14535        // Clean accounts, which should add earlier slots to the shrink
14536        // candidate set
14537        bank2.clean_accounts(false, false, None);
14538
14539        let mut bank3 = Arc::new(Bank::new_from_parent(&bank2, &Pubkey::default(), 3));
14540        bank3.deposit(&pubkey1, some_lamports + 1).unwrap();
14541        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank3).unwrap());
14542        bank3.freeze();
14543        bank3.squash();
14544        bank3.force_flush_accounts_cache();
14545
14546        bank3.clean_accounts(false, false, None);
14547        assert_eq!(
14548            bank3.rc.accounts.accounts_db.ref_count_for_pubkey(&pubkey0),
14549            2
14550        );
14551        assert!(bank3
14552            .rc
14553            .accounts
14554            .accounts_db
14555            .storage
14556            .get_slot_stores(1)
14557            .is_none());
14558
14559        bank3.print_accounts_stats();
14560    }
14561
14562    #[test]
14563    fn test_shrink_candidate_slots_cached() {
14564        solana_logger::setup();
14565
14566        let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000_000);
14567        let pubkey0 = solana_sdk::pubkey::new_rand();
14568        let pubkey1 = solana_sdk::pubkey::new_rand();
14569        let pubkey2 = solana_sdk::pubkey::new_rand();
14570
14571        // Set root for bank 0, with caching enabled
14572        let mut bank0 = Arc::new(Bank::new_with_config_for_tests(
14573            &genesis_config,
14574            AccountSecondaryIndexes::default(),
14575            true,
14576            AccountShrinkThreshold::default(),
14577        ));
14578        bank0.restore_old_behavior_for_fragile_tests();
14579
14580        let pubkey0_size = get_shrink_account_size();
14581
14582        let account0 = AccountSharedData::new(1000, pubkey0_size as usize, &Pubkey::new_unique());
14583        bank0.store_account(&pubkey0, &account0);
14584
14585        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank0).unwrap());
14586        bank0.freeze();
14587        bank0.squash();
14588        // Flush now so that accounts cache cleaning doesn't clean up bank 0 when later
14589        // slots add updates to the cache
14590        bank0.force_flush_accounts_cache();
14591
14592        // Store some lamports in bank 1
14593        let some_lamports = 123;
14594        let mut bank1 = Arc::new(new_from_parent(&bank0));
14595        bank1.deposit(&pubkey1, some_lamports).unwrap();
14596        bank1.deposit(&pubkey2, some_lamports).unwrap();
14597        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank1).unwrap());
14598        bank1.freeze();
14599        bank1.squash();
14600        // Flush now so that accounts cache cleaning doesn't clean up bank 0 when later
14601        // slots add updates to the cache
14602        bank1.force_flush_accounts_cache();
14603
14604        // Store some lamports for pubkey1 in bank 2, root bank 2
14605        let mut bank2 = Arc::new(new_from_parent(&bank1));
14606        bank2.deposit(&pubkey1, some_lamports).unwrap();
14607        bank2.store_account(&pubkey0, &account0);
14608        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank2).unwrap());
14609        bank2.freeze();
14610        bank2.squash();
14611        bank2.force_flush_accounts_cache();
14612
14613        // Clean accounts, which should add earlier slots to the shrink
14614        // candidate set
14615        bank2.clean_accounts(false, false, None);
14616
14617        // Slots 0 and 1 should be candidates for shrinking, but slot 2
14618        // shouldn't because none of its accounts are outdated by a later
14619        // root
14620        assert_eq!(bank2.shrink_candidate_slots(), 2);
14621        let alive_counts: Vec<usize> = (0..3)
14622            .map(|slot| {
14623                bank2
14624                    .rc
14625                    .accounts
14626                    .accounts_db
14627                    .alive_account_count_in_slot(slot)
14628            })
14629            .collect();
14630
14631        // No more slots should be shrunk
14632        assert_eq!(bank2.shrink_candidate_slots(), 0);
14633        // alive_counts represents the count of alive accounts in the three slots 0,1,2
14634        assert_eq!(alive_counts, vec![9, 1, 7]);
14635    }
14636
14637    #[test]
14638    fn test_process_stale_slot_with_budget() {
14639        solana_logger::setup();
14640        let pubkey1 = solana_sdk::pubkey::new_rand();
14641        let pubkey2 = solana_sdk::pubkey::new_rand();
14642
14643        let mut bank = create_simple_test_arc_bank(1_000_000_000);
14644        bank.restore_old_behavior_for_fragile_tests();
14645        assert_eq!(bank.process_stale_slot_with_budget(0, 0), 0);
14646        assert_eq!(bank.process_stale_slot_with_budget(133, 0), 133);
14647
14648        assert_eq!(bank.process_stale_slot_with_budget(0, 100), 0);
14649        assert_eq!(bank.process_stale_slot_with_budget(33, 100), 0);
14650        assert_eq!(bank.process_stale_slot_with_budget(133, 100), 33);
14651
14652        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank).unwrap());
14653
14654        bank.squash();
14655
14656        let some_lamports = 123;
14657        let mut bank = Arc::new(new_from_parent(&bank));
14658        bank.deposit(&pubkey1, some_lamports).unwrap();
14659        bank.deposit(&pubkey2, some_lamports).unwrap();
14660
14661        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank).unwrap());
14662
14663        let mut bank = Arc::new(new_from_parent(&bank));
14664        bank.deposit(&pubkey1, some_lamports).unwrap();
14665
14666        goto_end_of_slot(Arc::<Bank>::get_mut(&mut bank).unwrap());
14667
14668        bank.squash();
14669        bank.clean_accounts(false, false, None);
14670        let force_to_return_alive_account = 0;
14671        assert_eq!(
14672            bank.process_stale_slot_with_budget(22, force_to_return_alive_account),
14673            22
14674        );
14675
14676        let consumed_budgets: usize = (0..3)
14677            .map(|_| bank.process_stale_slot_with_budget(0, force_to_return_alive_account))
14678            .sum();
14679        // consumed_budgets represents the count of alive accounts in the three slots 0,1,2
14680        assert_eq!(consumed_budgets, 10);
14681    }
14682
14683    #[test]
14684    fn test_add_builtin_no_overwrite() {
14685        #[allow(clippy::unnecessary_wraps)]
14686        fn mock_ix_processor(
14687            _first_instruction_account: usize,
14688            _invoke_context: &mut InvokeContext,
14689        ) -> std::result::Result<(), InstructionError> {
14690            Ok(())
14691        }
14692
14693        let slot = 123;
14694        let program_id = solana_sdk::pubkey::new_rand();
14695
14696        let mut bank = Arc::new(Bank::new_from_parent(
14697            &create_simple_test_arc_bank(100_000),
14698            &Pubkey::default(),
14699            slot,
14700        ));
14701        assert_eq!(bank.get_account_modified_slot(&program_id), None);
14702
14703        Arc::get_mut(&mut bank).unwrap().add_builtin(
14704            "mock_program",
14705            &program_id,
14706            mock_ix_processor,
14707        );
14708        assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14709
14710        let mut bank = Arc::new(new_from_parent(&bank));
14711        Arc::get_mut(&mut bank).unwrap().add_builtin(
14712            "mock_program",
14713            &program_id,
14714            mock_ix_processor,
14715        );
14716        assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14717    }
14718
14719    #[test]
14720    fn test_add_builtin_loader_no_overwrite() {
14721        #[allow(clippy::unnecessary_wraps)]
14722        fn mock_ix_processor(
14723            _first_instruction_account: usize,
14724            _context: &mut InvokeContext,
14725        ) -> std::result::Result<(), InstructionError> {
14726            Ok(())
14727        }
14728
14729        let slot = 123;
14730        let loader_id = solana_sdk::pubkey::new_rand();
14731
14732        let mut bank = Arc::new(Bank::new_from_parent(
14733            &create_simple_test_arc_bank(100_000),
14734            &Pubkey::default(),
14735            slot,
14736        ));
14737        assert_eq!(bank.get_account_modified_slot(&loader_id), None);
14738
14739        Arc::get_mut(&mut bank)
14740            .unwrap()
14741            .add_builtin("mock_program", &loader_id, mock_ix_processor);
14742        assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot);
14743
14744        let mut bank = Arc::new(new_from_parent(&bank));
14745        Arc::get_mut(&mut bank)
14746            .unwrap()
14747            .add_builtin("mock_program", &loader_id, mock_ix_processor);
14748        assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot);
14749    }
14750
14751    #[test]
14752    fn test_add_builtin_account() {
14753        let (mut genesis_config, _mint_keypair) = create_genesis_config(100_000);
14754        activate_all_features(&mut genesis_config);
14755
14756        let slot = 123;
14757        let program_id = solana_sdk::pubkey::new_rand();
14758
14759        let bank = Arc::new(Bank::new_from_parent(
14760            &Arc::new(Bank::new_for_tests(&genesis_config)),
14761            &Pubkey::default(),
14762            slot,
14763        ));
14764        assert_eq!(bank.get_account_modified_slot(&program_id), None);
14765
14766        assert_capitalization_diff(
14767            &bank,
14768            || bank.add_builtin_account("mock_program", &program_id, false),
14769            |old, new| {
14770                assert_eq!(old + 1, new);
14771            },
14772        );
14773
14774        assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14775
14776        let bank = Arc::new(new_from_parent(&bank));
14777        assert_capitalization_diff(
14778            &bank,
14779            || bank.add_builtin_account("mock_program", &program_id, false),
14780            |old, new| assert_eq!(old, new),
14781        );
14782
14783        assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14784
14785        let bank = Arc::new(new_from_parent(&bank));
14786        // When replacing builtin_program, name must change to disambiguate from repeated
14787        // invocations.
14788        assert_capitalization_diff(
14789            &bank,
14790            || bank.add_builtin_account("mock_program v2", &program_id, true),
14791            |old, new| assert_eq!(old, new),
14792        );
14793
14794        assert_eq!(
14795            bank.get_account_modified_slot(&program_id).unwrap().1,
14796            bank.slot()
14797        );
14798
14799        let bank = Arc::new(new_from_parent(&bank));
14800        assert_capitalization_diff(
14801            &bank,
14802            || bank.add_builtin_account("mock_program v2", &program_id, true),
14803            |old, new| assert_eq!(old, new),
14804        );
14805
14806        // replacing with same name shouldn't update account
14807        assert_eq!(
14808            bank.get_account_modified_slot(&program_id).unwrap().1,
14809            bank.parent_slot()
14810        );
14811    }
14812
14813    #[test]
14814    fn test_add_builtin_account_inherited_cap_while_replacing() {
14815        let (genesis_config, mint_keypair) = create_genesis_config(100_000);
14816        let bank = Bank::new_for_tests(&genesis_config);
14817        let program_id = solana_sdk::pubkey::new_rand();
14818
14819        bank.add_builtin_account("mock_program", &program_id, false);
14820        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14821
14822        // someone mess with program_id's balance
14823        bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
14824        assert_ne!(bank.capitalization(), bank.calculate_capitalization(true));
14825        bank.deposit(&program_id, 10).unwrap();
14826        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14827
14828        bank.add_builtin_account("mock_program v2", &program_id, true);
14829        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14830    }
14831
14832    #[test]
14833    fn test_add_builtin_account_squatted_while_not_replacing() {
14834        let (genesis_config, mint_keypair) = create_genesis_config(100_000);
14835        let bank = Bank::new_for_tests(&genesis_config);
14836        let program_id = solana_sdk::pubkey::new_rand();
14837
14838        // someone managed to squat at program_id!
14839        bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
14840        assert_ne!(bank.capitalization(), bank.calculate_capitalization(true));
14841        bank.deposit(&program_id, 10).unwrap();
14842        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14843
14844        bank.add_builtin_account("mock_program", &program_id, false);
14845        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14846    }
14847
14848    #[test]
14849    #[should_panic(
14850        expected = "Can't change frozen bank by adding not-existing new builtin \
14851                   program (mock_program, EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK). \
14852                   Maybe, inconsistent program activation is detected on snapshot restore?"
14853    )]
14854    fn test_add_builtin_account_after_frozen() {
14855        let slot = 123;
14856        let program_id = Pubkey::from_str("EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK").unwrap();
14857
14858        let bank = Bank::new_from_parent(
14859            &create_simple_test_arc_bank(100_000),
14860            &Pubkey::default(),
14861            slot,
14862        );
14863        bank.freeze();
14864
14865        bank.add_builtin_account("mock_program", &program_id, false);
14866    }
14867
14868    #[test]
14869    #[should_panic(
14870        expected = "There is no account to replace with builtin program (mock_program, \
14871                    EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK)."
14872    )]
14873    fn test_add_builtin_account_replace_none() {
14874        let slot = 123;
14875        let program_id = Pubkey::from_str("EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK").unwrap();
14876
14877        let bank = Bank::new_from_parent(
14878            &create_simple_test_arc_bank(100_000),
14879            &Pubkey::default(),
14880            slot,
14881        );
14882
14883        bank.add_builtin_account("mock_program", &program_id, true);
14884    }
14885
14886    #[test]
14887    fn test_add_precompiled_account() {
14888        let (mut genesis_config, _mint_keypair) = create_genesis_config(100_000);
14889        activate_all_features(&mut genesis_config);
14890
14891        let slot = 123;
14892        let program_id = solana_sdk::pubkey::new_rand();
14893
14894        let bank = Arc::new(Bank::new_from_parent(
14895            &Arc::new(Bank::new_for_tests(&genesis_config)),
14896            &Pubkey::default(),
14897            slot,
14898        ));
14899        assert_eq!(bank.get_account_modified_slot(&program_id), None);
14900
14901        assert_capitalization_diff(
14902            &bank,
14903            || bank.add_precompiled_account(&program_id),
14904            |old, new| {
14905                assert_eq!(old + 1, new);
14906            },
14907        );
14908
14909        assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14910
14911        let bank = Arc::new(new_from_parent(&bank));
14912        assert_capitalization_diff(
14913            &bank,
14914            || bank.add_precompiled_account(&program_id),
14915            |old, new| assert_eq!(old, new),
14916        );
14917
14918        assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
14919    }
14920
14921    #[test]
14922    fn test_add_precompiled_account_inherited_cap_while_replacing() {
14923        let (genesis_config, mint_keypair) = create_genesis_config(100_000);
14924        let bank = Bank::new_for_tests(&genesis_config);
14925        let program_id = solana_sdk::pubkey::new_rand();
14926
14927        bank.add_precompiled_account(&program_id);
14928        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14929
14930        // someone mess with program_id's balance
14931        bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
14932        assert_ne!(bank.capitalization(), bank.calculate_capitalization(true));
14933        bank.deposit(&program_id, 10).unwrap();
14934        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14935
14936        bank.add_precompiled_account(&program_id);
14937        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14938    }
14939
14940    #[test]
14941    fn test_add_precompiled_account_squatted_while_not_replacing() {
14942        let (genesis_config, mint_keypair) = create_genesis_config(100_000);
14943        let bank = Bank::new_for_tests(&genesis_config);
14944        let program_id = solana_sdk::pubkey::new_rand();
14945
14946        // someone managed to squat at program_id!
14947        bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
14948        assert_ne!(bank.capitalization(), bank.calculate_capitalization(true));
14949        bank.deposit(&program_id, 10).unwrap();
14950        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14951
14952        bank.add_precompiled_account(&program_id);
14953        assert_eq!(bank.capitalization(), bank.calculate_capitalization(true));
14954    }
14955
14956    #[test]
14957    #[should_panic(
14958        expected = "Can't change frozen bank by adding not-existing new precompiled \
14959                   program (EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK). \
14960                   Maybe, inconsistent program activation is detected on snapshot restore?"
14961    )]
14962    fn test_add_precompiled_account_after_frozen() {
14963        let slot = 123;
14964        let program_id = Pubkey::from_str("EJ7BZ5wk1brwAGwnVmsGauQCRS4btvabkrdn1MpDrUHK").unwrap();
14965
14966        let bank = Bank::new_from_parent(
14967            &create_simple_test_arc_bank(100_000),
14968            &Pubkey::default(),
14969            slot,
14970        );
14971        bank.freeze();
14972
14973        bank.add_precompiled_account(&program_id);
14974    }
14975
14976    #[test]
14977    fn test_reconfigure_token2_native_mint() {
14978        solana_logger::setup();
14979
14980        let mut genesis_config =
14981            create_genesis_config_with_leader(5, &solana_sdk::pubkey::new_rand(), 0).genesis_config;
14982
14983        // ClusterType::Development - Native mint exists immediately
14984        assert_eq!(genesis_config.cluster_type, ClusterType::Development);
14985        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
14986        assert_eq!(
14987            bank.get_balance(&inline_safe_token::native_mint::id()),
14988            1000000000
14989        );
14990
14991        // Testnet - Native mint blinks into existence at epoch 93
14992        genesis_config.cluster_type = ClusterType::Testnet;
14993        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
14994        assert_eq!(bank.get_balance(&inline_safe_token::native_mint::id()), 0);
14995        bank.deposit(&inline_safe_token::native_mint::id(), 4200000000)
14996            .unwrap();
14997
14998        let bank = Bank::new_from_parent(
14999            &bank,
15000            &Pubkey::default(),
15001            genesis_config.epoch_schedule.get_first_slot_in_epoch(93),
15002        );
15003
15004        let native_mint_account = bank
15005            .get_account(&inline_safe_token::native_mint::id())
15006            .unwrap();
15007        assert_eq!(native_mint_account.data().len(), 82);
15008        assert_eq!(
15009            bank.get_balance(&inline_safe_token::native_mint::id()),
15010            4200000000
15011        );
15012        assert_eq!(native_mint_account.owner(), &inline_safe_token::id());
15013
15014        // MainnetBeta - Native mint blinks into existence at epoch 75
15015        genesis_config.cluster_type = ClusterType::MainnetBeta;
15016        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
15017        assert_eq!(bank.get_balance(&inline_safe_token::native_mint::id()), 0);
15018        bank.deposit(&inline_safe_token::native_mint::id(), 4200000000)
15019            .unwrap();
15020
15021        let bank = Bank::new_from_parent(
15022            &bank,
15023            &Pubkey::default(),
15024            genesis_config.epoch_schedule.get_first_slot_in_epoch(75),
15025        );
15026
15027        let native_mint_account = bank
15028            .get_account(&inline_safe_token::native_mint::id())
15029            .unwrap();
15030        assert_eq!(native_mint_account.data().len(), 82);
15031        assert_eq!(
15032            bank.get_balance(&inline_safe_token::native_mint::id()),
15033            4200000000
15034        );
15035        assert_eq!(native_mint_account.owner(), &inline_safe_token::id());
15036    }
15037
15038    #[test]
15039    fn test_ensure_no_storage_rewards_pool() {
15040        solana_logger::setup();
15041
15042        let mut genesis_config =
15043            create_genesis_config_with_leader(5, &solana_sdk::pubkey::new_rand(), 0).genesis_config;
15044
15045        // Testnet - Storage rewards pool is purged at epoch 93
15046        // Also this is with bad capitalization
15047        genesis_config.cluster_type = ClusterType::Testnet;
15048        genesis_config.inflation = Inflation::default();
15049        let reward_pubkey = solana_sdk::pubkey::new_rand();
15050        genesis_config.rewards_pools.insert(
15051            reward_pubkey,
15052            Account::new(u64::MAX, 0, &solana_sdk::pubkey::new_rand()),
15053        );
15054        let bank0 = Bank::new_for_tests(&genesis_config);
15055        // because capitalization has been reset with bogus capitalization calculation allowing overflows,
15056        // deliberately substract 1 lamport to simulate it
15057        bank0.capitalization.fetch_sub(1, Relaxed);
15058        let bank0 = Arc::new(bank0);
15059        assert_eq!(bank0.get_balance(&reward_pubkey), u64::MAX,);
15060
15061        let bank1 = Bank::new_from_parent(
15062            &bank0,
15063            &Pubkey::default(),
15064            genesis_config.epoch_schedule.get_first_slot_in_epoch(93),
15065        );
15066
15067        // assert that everything gets in order....
15068        assert!(bank1.get_account(&reward_pubkey).is_none());
15069        let sysvar_and_builtin_program_delta = 1;
15070        assert_eq!(
15071            bank0.capitalization() + 1 + 1_000_000_000 + sysvar_and_builtin_program_delta,
15072            bank1.capitalization()
15073        );
15074        assert_eq!(bank1.capitalization(), bank1.calculate_capitalization(true));
15075
15076        // Depending on RUSTFLAGS, this test exposes rust's checked math behavior or not...
15077        // So do some convolted setup; anyway this test itself will just be temporary
15078        let bank0 = std::panic::AssertUnwindSafe(bank0);
15079        let overflowing_capitalization =
15080            std::panic::catch_unwind(|| bank0.calculate_capitalization(true));
15081        if let Ok(overflowing_capitalization) = overflowing_capitalization {
15082            info!("asserting overflowing capitalization for bank0");
15083            assert_eq!(overflowing_capitalization, bank0.capitalization());
15084        } else {
15085            info!("NOT-asserting overflowing capitalization for bank0");
15086        }
15087    }
15088
15089    #[derive(Debug)]
15090    struct TestExecutor {}
15091    impl Executor for TestExecutor {
15092        fn execute(
15093            &self,
15094            _first_instruction_account: usize,
15095            _invoke_context: &mut InvokeContext,
15096        ) -> std::result::Result<(), InstructionError> {
15097            Ok(())
15098        }
15099    }
15100
15101    #[test]
15102    fn test_bank_executor_cache() {
15103        solana_logger::setup();
15104
15105        let (genesis_config, _) = create_genesis_config(1);
15106        let bank = Bank::new_for_tests(&genesis_config);
15107
15108        let key1 = solana_sdk::pubkey::new_rand();
15109        let key2 = solana_sdk::pubkey::new_rand();
15110        let key3 = solana_sdk::pubkey::new_rand();
15111        let key4 = solana_sdk::pubkey::new_rand();
15112        let key5 = solana_sdk::pubkey::new_rand();
15113        let executor: Arc<dyn Executor> = Arc::new(TestExecutor {});
15114
15115        fn new_executable_account(owner: Pubkey) -> AccountSharedData {
15116            AccountSharedData::from(Account {
15117                owner,
15118                executable: true,
15119                ..Account::default()
15120            })
15121        }
15122
15123        let accounts = &[
15124            (key1, new_executable_account(bpf_loader_upgradeable::id())),
15125            (key2, new_executable_account(bpf_loader::id())),
15126            (key3, new_executable_account(bpf_loader_deprecated::id())),
15127            (key4, new_executable_account(native_loader::id())),
15128            (key5, AccountSharedData::default()),
15129        ];
15130
15131        // don't do any work if not dirty
15132        let mut executors = Executors::default();
15133        executors.insert(key1, TransactionExecutor::new_cached(executor.clone()));
15134        executors.insert(key2, TransactionExecutor::new_cached(executor.clone()));
15135        executors.insert(key3, TransactionExecutor::new_cached(executor.clone()));
15136        executors.insert(key4, TransactionExecutor::new_cached(executor.clone()));
15137        let executors = Rc::new(RefCell::new(executors));
15138        bank.store_missing_executors(&executors);
15139        bank.store_updated_executors(&executors);
15140        let executors = bank.get_executors(accounts);
15141        assert_eq!(executors.borrow().len(), 0);
15142
15143        // do work
15144        let mut executors = Executors::default();
15145        executors.insert(key1, TransactionExecutor::new_miss(executor.clone()));
15146        executors.insert(key2, TransactionExecutor::new_miss(executor.clone()));
15147        executors.insert(key3, TransactionExecutor::new_updated(executor.clone()));
15148        executors.insert(key4, TransactionExecutor::new_miss(executor.clone()));
15149        let executors = Rc::new(RefCell::new(executors));
15150
15151        // store the new_miss
15152        bank.store_missing_executors(&executors);
15153        let stored_executors = bank.get_executors(accounts);
15154        assert_eq!(stored_executors.borrow().len(), 2);
15155        assert!(stored_executors.borrow().contains_key(&key1));
15156        assert!(stored_executors.borrow().contains_key(&key2));
15157
15158        // store the new_updated
15159        bank.store_updated_executors(&executors);
15160        let stored_executors = bank.get_executors(accounts);
15161        assert_eq!(stored_executors.borrow().len(), 3);
15162        assert!(stored_executors.borrow().contains_key(&key1));
15163        assert!(stored_executors.borrow().contains_key(&key2));
15164        assert!(stored_executors.borrow().contains_key(&key3));
15165
15166        // Check inheritance
15167        let bank = Bank::new_from_parent(&Arc::new(bank), &solana_sdk::pubkey::new_rand(), 1);
15168        let executors = bank.get_executors(accounts);
15169        assert_eq!(executors.borrow().len(), 3);
15170        assert!(executors.borrow().contains_key(&key1));
15171        assert!(executors.borrow().contains_key(&key2));
15172        assert!(executors.borrow().contains_key(&key3));
15173
15174        // Remove all
15175        bank.remove_executor(&key1);
15176        bank.remove_executor(&key2);
15177        bank.remove_executor(&key3);
15178        bank.remove_executor(&key4);
15179        let executors = bank.get_executors(accounts);
15180        assert_eq!(executors.borrow().len(), 0);
15181    }
15182
15183    #[test]
15184    fn test_bank_executor_cow() {
15185        solana_logger::setup();
15186
15187        let (genesis_config, _) = create_genesis_config(1);
15188        let root = Arc::new(Bank::new_for_tests(&genesis_config));
15189
15190        let key1 = solana_sdk::pubkey::new_rand();
15191        let key2 = solana_sdk::pubkey::new_rand();
15192        let executor: Arc<dyn Executor> = Arc::new(TestExecutor {});
15193        let executable_account = AccountSharedData::from(Account {
15194            owner: bpf_loader_upgradeable::id(),
15195            executable: true,
15196            ..Account::default()
15197        });
15198
15199        let accounts = &[
15200            (key1, executable_account.clone()),
15201            (key2, executable_account),
15202        ];
15203
15204        // add one to root bank
15205        let mut executors = Executors::default();
15206        executors.insert(key1, TransactionExecutor::new_miss(executor.clone()));
15207        let executors = Rc::new(RefCell::new(executors));
15208        root.store_missing_executors(&executors);
15209        let executors = root.get_executors(accounts);
15210        assert_eq!(executors.borrow().len(), 1);
15211
15212        let fork1 = Bank::new_from_parent(&root, &Pubkey::default(), 1);
15213        let fork2 = Bank::new_from_parent(&root, &Pubkey::default(), 2);
15214
15215        let executors = fork1.get_executors(accounts);
15216        assert_eq!(executors.borrow().len(), 1);
15217        let executors = fork2.get_executors(accounts);
15218        assert_eq!(executors.borrow().len(), 1);
15219
15220        let mut executors = Executors::default();
15221        executors.insert(key2, TransactionExecutor::new_miss(executor.clone()));
15222        let executors = Rc::new(RefCell::new(executors));
15223        fork1.store_missing_executors(&executors);
15224
15225        let executors = fork1.get_executors(accounts);
15226        assert_eq!(executors.borrow().len(), 2);
15227        let executors = fork2.get_executors(accounts);
15228        assert_eq!(executors.borrow().len(), 1);
15229
15230        fork1.remove_executor(&key1);
15231
15232        let executors = fork1.get_executors(accounts);
15233        assert_eq!(executors.borrow().len(), 1);
15234        let executors = fork2.get_executors(accounts);
15235        assert_eq!(executors.borrow().len(), 1);
15236    }
15237
15238    #[test]
15239    fn test_compute_active_feature_set() {
15240        let bank0 = create_simple_test_arc_bank(100_000);
15241        let mut bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
15242
15243        let test_feature = "TestFeature11111111111111111111111111111111"
15244            .parse::<Pubkey>()
15245            .unwrap();
15246        let mut feature_set = FeatureSet::default();
15247        feature_set.inactive.insert(test_feature);
15248        bank.feature_set = Arc::new(feature_set.clone());
15249
15250        let new_activations = bank.compute_active_feature_set(true);
15251        assert!(new_activations.is_empty());
15252        assert!(!bank.feature_set.is_active(&test_feature));
15253
15254        // Depositing into the `test_feature` account should do nothing
15255        bank.deposit(&test_feature, 42).unwrap();
15256        let new_activations = bank.compute_active_feature_set(true);
15257        assert!(new_activations.is_empty());
15258        assert!(!bank.feature_set.is_active(&test_feature));
15259
15260        // Request `test_feature` activation
15261        let feature = Feature::default();
15262        assert_eq!(feature.activated_at, None);
15263        bank.store_account(&test_feature, &feature::create_account(&feature, 42));
15264
15265        // Run `compute_active_feature_set` disallowing new activations
15266        let new_activations = bank.compute_active_feature_set(false);
15267        assert!(new_activations.is_empty());
15268        assert!(!bank.feature_set.is_active(&test_feature));
15269        let feature = feature::from_account(&bank.get_account(&test_feature).expect("get_account"))
15270            .expect("from_account");
15271        assert_eq!(feature.activated_at, None);
15272
15273        // Run `compute_active_feature_set` allowing new activations
15274        let new_activations = bank.compute_active_feature_set(true);
15275        assert_eq!(new_activations.len(), 1);
15276        assert!(bank.feature_set.is_active(&test_feature));
15277        let feature = feature::from_account(&bank.get_account(&test_feature).expect("get_account"))
15278            .expect("from_account");
15279        assert_eq!(feature.activated_at, Some(1));
15280
15281        // Reset the bank's feature set
15282        bank.feature_set = Arc::new(feature_set);
15283        assert!(!bank.feature_set.is_active(&test_feature));
15284
15285        // Running `compute_active_feature_set` will not cause new activations, but
15286        // `test_feature` is now be active
15287        let new_activations = bank.compute_active_feature_set(true);
15288        assert!(new_activations.is_empty());
15289        assert!(bank.feature_set.is_active(&test_feature));
15290    }
15291
15292    #[test]
15293    fn test_program_replacement() {
15294        let mut bank = create_simple_test_bank(0);
15295
15296        // Setup original program account
15297        let old_address = Pubkey::new_unique();
15298        let new_address = Pubkey::new_unique();
15299        bank.store_account_and_update_capitalization(
15300            &old_address,
15301            &AccountSharedData::from(Account {
15302                lamports: 100,
15303                ..Account::default()
15304            }),
15305        );
15306        assert_eq!(bank.get_balance(&old_address), 100);
15307
15308        // Setup new program account
15309        let new_program_account = AccountSharedData::from(Account {
15310            lamports: 123,
15311            ..Account::default()
15312        });
15313        bank.store_account_and_update_capitalization(&new_address, &new_program_account);
15314        assert_eq!(bank.get_balance(&new_address), 123);
15315
15316        let original_capitalization = bank.capitalization();
15317
15318        bank.replace_program_account(&old_address, &new_address, "bank-apply_program_replacement");
15319
15320        // New program account is now empty
15321        assert_eq!(bank.get_balance(&new_address), 0);
15322
15323        // Old program account holds the new program account
15324        assert_eq!(bank.get_account(&old_address), Some(new_program_account));
15325
15326        // Lamports in the old token account were burnt
15327        assert_eq!(bank.capitalization(), original_capitalization - 100);
15328    }
15329
15330    pub fn update_vote_account_timestamp(
15331        timestamp: BlockTimestamp,
15332        bank: &Bank,
15333        vote_pubkey: &Pubkey,
15334    ) {
15335        let mut vote_account = bank.get_account(vote_pubkey).unwrap_or_default();
15336        let mut vote_state = VoteState::from(&vote_account).unwrap_or_default();
15337        vote_state.last_timestamp = timestamp;
15338        let versioned = VoteStateVersions::new_current(vote_state);
15339        VoteState::to(&versioned, &mut vote_account).unwrap();
15340        bank.store_account(vote_pubkey, &vote_account);
15341    }
15342
15343    fn min_rent_excempt_balance_for_sysvars(bank: &Bank, sysvar_ids: &[Pubkey]) -> u64 {
15344        sysvar_ids
15345            .iter()
15346            .map(|sysvar_id| {
15347                trace!("min_rent_excempt_balance_for_sysvars: {}", sysvar_id);
15348                bank.get_minimum_balance_for_rent_exemption(
15349                    bank.get_account(sysvar_id).unwrap().data().len(),
15350                )
15351            })
15352            .sum()
15353    }
15354
15355    #[test]
15356    fn test_adjust_sysvar_balance_for_rent() {
15357        let bank = create_simple_test_bank(0);
15358        let mut smaller_sample_sysvar = AccountSharedData::new(1, 0, &Pubkey::default());
15359        assert_eq!(smaller_sample_sysvar.lamports(), 1);
15360        bank.adjust_sysvar_balance_for_rent(&mut smaller_sample_sysvar);
15361        assert_eq!(
15362            smaller_sample_sysvar.lamports(),
15363            bank.get_minimum_balance_for_rent_exemption(smaller_sample_sysvar.data().len()),
15364        );
15365
15366        let mut bigger_sample_sysvar = AccountSharedData::new(
15367            1,
15368            smaller_sample_sysvar.data().len() + 1,
15369            &Pubkey::default(),
15370        );
15371        bank.adjust_sysvar_balance_for_rent(&mut bigger_sample_sysvar);
15372        assert!(smaller_sample_sysvar.lamports() < bigger_sample_sysvar.lamports());
15373
15374        // excess lamports shouldn't be reduced by adjust_sysvar_balance_for_rent()
15375        let excess_lamports = smaller_sample_sysvar.lamports() + 999;
15376        smaller_sample_sysvar.set_lamports(excess_lamports);
15377        bank.adjust_sysvar_balance_for_rent(&mut smaller_sample_sysvar);
15378        assert_eq!(smaller_sample_sysvar.lamports(), excess_lamports);
15379    }
15380
15381    #[test]
15382    fn test_update_clock_timestamp() {
15383        let leader_pubkey = solana_sdk::pubkey::new_rand();
15384        let GenesisConfigInfo {
15385            genesis_config,
15386            voting_keypair,
15387            ..
15388        } = create_genesis_config_with_leader(5, &leader_pubkey, 3);
15389        let mut bank = Bank::new_for_tests(&genesis_config);
15390        // Advance past slot 0, which has special handling.
15391        bank = new_from_parent(&Arc::new(bank));
15392        bank = new_from_parent(&Arc::new(bank));
15393        assert_eq!(
15394            bank.clock().unix_timestamp,
15395            bank.unix_timestamp_from_genesis()
15396        );
15397
15398        bank.update_clock(None);
15399        assert_eq!(
15400            bank.clock().unix_timestamp,
15401            bank.unix_timestamp_from_genesis()
15402        );
15403
15404        update_vote_account_timestamp(
15405            BlockTimestamp {
15406                slot: bank.slot(),
15407                timestamp: bank.unix_timestamp_from_genesis() - 1,
15408            },
15409            &bank,
15410            &voting_keypair.pubkey(),
15411        );
15412        bank.update_clock(None);
15413        assert_eq!(
15414            bank.clock().unix_timestamp,
15415            bank.unix_timestamp_from_genesis()
15416        );
15417
15418        update_vote_account_timestamp(
15419            BlockTimestamp {
15420                slot: bank.slot(),
15421                timestamp: bank.unix_timestamp_from_genesis(),
15422            },
15423            &bank,
15424            &voting_keypair.pubkey(),
15425        );
15426        bank.update_clock(None);
15427        assert_eq!(
15428            bank.clock().unix_timestamp,
15429            bank.unix_timestamp_from_genesis()
15430        );
15431
15432        update_vote_account_timestamp(
15433            BlockTimestamp {
15434                slot: bank.slot(),
15435                timestamp: bank.unix_timestamp_from_genesis() + 1,
15436            },
15437            &bank,
15438            &voting_keypair.pubkey(),
15439        );
15440        bank.update_clock(None);
15441        assert_eq!(
15442            bank.clock().unix_timestamp,
15443            bank.unix_timestamp_from_genesis() + 1
15444        );
15445
15446        // Timestamp cannot go backward from ancestor Bank to child
15447        bank = new_from_parent(&Arc::new(bank));
15448        update_vote_account_timestamp(
15449            BlockTimestamp {
15450                slot: bank.slot(),
15451                timestamp: bank.unix_timestamp_from_genesis() - 1,
15452            },
15453            &bank,
15454            &voting_keypair.pubkey(),
15455        );
15456        bank.update_clock(None);
15457        assert_eq!(
15458            bank.clock().unix_timestamp,
15459            bank.unix_timestamp_from_genesis()
15460        );
15461    }
15462
15463    fn poh_estimate_offset(bank: &Bank) -> Duration {
15464        let mut epoch_start_slot = bank.epoch_schedule.get_first_slot_in_epoch(bank.epoch());
15465        if epoch_start_slot == bank.slot() {
15466            epoch_start_slot = bank
15467                .epoch_schedule
15468                .get_first_slot_in_epoch(bank.epoch() - 1);
15469        }
15470        bank.slot().saturating_sub(epoch_start_slot) as u32
15471            * Duration::from_nanos(bank.ns_per_slot as u64)
15472    }
15473
15474    #[test]
15475    fn test_timestamp_slow() {
15476        fn max_allowable_delta_since_epoch(bank: &Bank, max_allowable_drift: u32) -> i64 {
15477            let poh_estimate_offset = poh_estimate_offset(bank);
15478            (poh_estimate_offset.as_secs()
15479                + (poh_estimate_offset * max_allowable_drift / 100).as_secs()) as i64
15480        }
15481
15482        let leader_pubkey = solana_sdk::pubkey::new_rand();
15483        let GenesisConfigInfo {
15484            mut genesis_config,
15485            voting_keypair,
15486            ..
15487        } = create_genesis_config_with_leader(5, &leader_pubkey, 3);
15488        let slots_in_epoch = 32;
15489        genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch);
15490        let mut bank = Bank::new_for_tests(&genesis_config);
15491        let slot_duration = Duration::from_nanos(bank.ns_per_slot as u64);
15492
15493        let recent_timestamp: UnixTimestamp = bank.unix_timestamp_from_genesis();
15494        let additional_secs = ((slot_duration * MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2 * 32) / 100)
15495            .as_secs() as i64
15496            + 1; // Greater than max_allowable_drift_slow_v2 for full epoch
15497        update_vote_account_timestamp(
15498            BlockTimestamp {
15499                slot: bank.slot(),
15500                timestamp: recent_timestamp + additional_secs,
15501            },
15502            &bank,
15503            &voting_keypair.pubkey(),
15504        );
15505
15506        // additional_secs greater than MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2 for an epoch
15507        // timestamp bounded to 150% deviation
15508        for _ in 0..31 {
15509            bank = new_from_parent(&Arc::new(bank));
15510            assert_eq!(
15511                bank.clock().unix_timestamp,
15512                bank.clock().epoch_start_timestamp
15513                    + max_allowable_delta_since_epoch(
15514                        &bank,
15515                        MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2
15516                    ),
15517            );
15518            assert_eq!(bank.clock().epoch_start_timestamp, recent_timestamp);
15519        }
15520    }
15521
15522    #[test]
15523    fn test_timestamp_fast() {
15524        fn max_allowable_delta_since_epoch(bank: &Bank, max_allowable_drift: u32) -> i64 {
15525            let poh_estimate_offset = poh_estimate_offset(bank);
15526            (poh_estimate_offset.as_secs()
15527                - (poh_estimate_offset * max_allowable_drift / 100).as_secs()) as i64
15528        }
15529
15530        let leader_pubkey = solana_sdk::pubkey::new_rand();
15531        let GenesisConfigInfo {
15532            mut genesis_config,
15533            voting_keypair,
15534            ..
15535        } = create_genesis_config_with_leader(5, &leader_pubkey, 3);
15536        let slots_in_epoch = 32;
15537        genesis_config.epoch_schedule = EpochSchedule::new(slots_in_epoch);
15538        let mut bank = Bank::new_for_tests(&genesis_config);
15539
15540        let recent_timestamp: UnixTimestamp = bank.unix_timestamp_from_genesis();
15541        let additional_secs = 5; // Greater than MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST for full epoch
15542        update_vote_account_timestamp(
15543            BlockTimestamp {
15544                slot: bank.slot(),
15545                timestamp: recent_timestamp - additional_secs,
15546            },
15547            &bank,
15548            &voting_keypair.pubkey(),
15549        );
15550
15551        // additional_secs greater than MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST for an epoch
15552        // timestamp bounded to 25% deviation
15553        for _ in 0..31 {
15554            bank = new_from_parent(&Arc::new(bank));
15555            assert_eq!(
15556                bank.clock().unix_timestamp,
15557                bank.clock().epoch_start_timestamp
15558                    + max_allowable_delta_since_epoch(&bank, MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST),
15559            );
15560            assert_eq!(bank.clock().epoch_start_timestamp, recent_timestamp);
15561        }
15562    }
15563
15564    #[test]
15565    fn test_program_is_native_loader() {
15566        let (genesis_config, mint_keypair) = create_genesis_config(50000);
15567        let bank = Bank::new_for_tests(&genesis_config);
15568
15569        let tx = Transaction::new_signed_with_payer(
15570            &[Instruction::new_with_bincode(
15571                native_loader::id(),
15572                &(),
15573                vec![],
15574            )],
15575            Some(&mint_keypair.pubkey()),
15576            &[&mint_keypair],
15577            bank.last_blockhash(),
15578        );
15579        assert_eq!(
15580            bank.process_transaction(&tx),
15581            Err(TransactionError::InstructionError(
15582                0,
15583                InstructionError::UnsupportedProgramId
15584            ))
15585        );
15586    }
15587
15588    #[test]
15589    fn test_debug_bank() {
15590        let (genesis_config, _mint_keypair) = create_genesis_config(50000);
15591        let mut bank = Bank::new_for_tests(&genesis_config);
15592        bank.finish_init(&genesis_config, None, false);
15593        let debug = format!("{:#?}", bank);
15594        assert!(!debug.is_empty());
15595    }
15596
15597    #[derive(Debug)]
15598    enum AcceptableScanResults {
15599        DroppedSlotError,
15600        NoFailure,
15601        Both,
15602    }
15603
15604    fn test_store_scan_consistency<F: 'static>(
15605        accounts_db_caching_enabled: bool,
15606        update_f: F,
15607        drop_callback: Option<Box<dyn DropCallback + Send + Sync>>,
15608        acceptable_scan_results: AcceptableScanResults,
15609    ) where
15610        F: Fn(
15611                Arc<Bank>,
15612                crossbeam_channel::Sender<Arc<Bank>>,
15613                crossbeam_channel::Receiver<BankId>,
15614                Arc<HashSet<Pubkey>>,
15615                Pubkey,
15616                u64,
15617            ) + std::marker::Send,
15618    {
15619        solana_logger::setup();
15620        // Set up initial bank
15621        let mut genesis_config = create_genesis_config_with_leader(
15622            10,
15623            &solana_sdk::pubkey::new_rand(),
15624            374_999_998_287_840,
15625        )
15626        .genesis_config;
15627        genesis_config.rent = Rent::free();
15628        let bank0 = Arc::new(Bank::new_with_config_for_tests(
15629            &genesis_config,
15630            AccountSecondaryIndexes::default(),
15631            accounts_db_caching_enabled,
15632            AccountShrinkThreshold::default(),
15633        ));
15634        bank0.set_callback(drop_callback);
15635
15636        // Set up pubkeys to write to
15637        let total_pubkeys = ITER_BATCH_SIZE * 10;
15638        let total_pubkeys_to_modify = 10;
15639        let all_pubkeys: Vec<Pubkey> = std::iter::repeat_with(solana_sdk::pubkey::new_rand)
15640            .take(total_pubkeys)
15641            .collect();
15642        let program_id = system_program::id();
15643        let starting_lamports = 1;
15644        let starting_account = AccountSharedData::new(starting_lamports, 0, &program_id);
15645
15646        // Write accounts to the store
15647        for key in &all_pubkeys {
15648            bank0.store_account(key, &starting_account);
15649        }
15650
15651        // Set aside a subset of accounts to modify
15652        let pubkeys_to_modify: Arc<HashSet<Pubkey>> = Arc::new(
15653            all_pubkeys
15654                .into_iter()
15655                .take(total_pubkeys_to_modify)
15656                .collect(),
15657        );
15658        let exit = Arc::new(AtomicBool::new(false));
15659
15660        // Thread that runs scan and constantly checks for
15661        // consistency
15662        let pubkeys_to_modify_ = pubkeys_to_modify.clone();
15663
15664        // Channel over which the bank to scan is sent
15665        let (bank_to_scan_sender, bank_to_scan_receiver): (
15666            crossbeam_channel::Sender<Arc<Bank>>,
15667            crossbeam_channel::Receiver<Arc<Bank>>,
15668        ) = bounded(1);
15669
15670        let (scan_finished_sender, scan_finished_receiver): (
15671            crossbeam_channel::Sender<BankId>,
15672            crossbeam_channel::Receiver<BankId>,
15673        ) = unbounded();
15674        let num_banks_scanned = Arc::new(AtomicU64::new(0));
15675        let scan_thread = {
15676            let exit = exit.clone();
15677            let num_banks_scanned = num_banks_scanned.clone();
15678            Builder::new()
15679                .name("scan".to_string())
15680                .spawn(move || {
15681                    loop {
15682                        info!("starting scan iteration");
15683                        if exit.load(Relaxed) {
15684                            info!("scan exiting");
15685                            return;
15686                        }
15687                        if let Ok(bank_to_scan) =
15688                            bank_to_scan_receiver.recv_timeout(Duration::from_millis(10))
15689                        {
15690                            info!("scanning program accounts for slot {}", bank_to_scan.slot());
15691                            let accounts_result = bank_to_scan
15692                                .get_program_accounts(&program_id, &ScanConfig::default());
15693                            let _ = scan_finished_sender.send(bank_to_scan.bank_id());
15694                            num_banks_scanned.fetch_add(1, Relaxed);
15695                            match (&acceptable_scan_results, accounts_result.is_err()) {
15696                                (AcceptableScanResults::DroppedSlotError, _)
15697                                | (AcceptableScanResults::Both, true) => {
15698                                    assert_eq!(
15699                                        accounts_result,
15700                                        Err(ScanError::SlotRemoved {
15701                                            slot: bank_to_scan.slot(),
15702                                            bank_id: bank_to_scan.bank_id()
15703                                        })
15704                                    );
15705                                }
15706                                (AcceptableScanResults::NoFailure, _)
15707                                | (AcceptableScanResults::Both, false) => {
15708                                    assert!(accounts_result.is_ok())
15709                                }
15710                            }
15711
15712                            // Should never see empty accounts because no slot ever deleted
15713                            // any of the original accounts, and the scan should reflect the
15714                            // account state at some frozen slot `X` (no partial updates).
15715                            if let Ok(accounts) = accounts_result {
15716                                assert!(!accounts.is_empty());
15717                                let mut expected_lamports = None;
15718                                let mut target_accounts_found = HashSet::new();
15719                                for (pubkey, account) in accounts {
15720                                    let account_balance = account.lamports();
15721                                    if pubkeys_to_modify_.contains(&pubkey) {
15722                                        target_accounts_found.insert(pubkey);
15723                                        if let Some(expected_lamports) = expected_lamports {
15724                                            assert_eq!(account_balance, expected_lamports);
15725                                        } else {
15726                                            // All pubkeys in the specified set should have the same balance
15727                                            expected_lamports = Some(account_balance);
15728                                        }
15729                                    }
15730                                }
15731
15732                                // Should've found all the accounts, i.e. no partial cleans should
15733                                // be detected
15734                                assert_eq!(target_accounts_found.len(), total_pubkeys_to_modify);
15735                            }
15736                        }
15737                    }
15738                })
15739                .unwrap()
15740        };
15741
15742        // Thread that constantly updates the accounts, sets
15743        // roots, and cleans
15744        let update_thread = Builder::new()
15745            .name("update".to_string())
15746            .spawn(move || {
15747                update_f(
15748                    bank0,
15749                    bank_to_scan_sender,
15750                    scan_finished_receiver,
15751                    pubkeys_to_modify,
15752                    program_id,
15753                    starting_lamports,
15754                );
15755            })
15756            .unwrap();
15757
15758        // Let threads run for a while, check the scans didn't see any mixed slots
15759        let min_expected_number_of_scans = 5;
15760        std::thread::sleep(Duration::new(5, 0));
15761        // This can be reduced when you are running this test locally to deal with hangs
15762        // But, if it is too low, the ci fails intermittently.
15763        let mut remaining_loops = 2000;
15764        loop {
15765            if num_banks_scanned.load(Relaxed) > min_expected_number_of_scans {
15766                break;
15767            } else {
15768                std::thread::sleep(Duration::from_millis(100));
15769            }
15770            remaining_loops -= 1;
15771            if remaining_loops == 0 {
15772                break; // just quit and try to get the thread result (panic, etc.)
15773            }
15774        }
15775        exit.store(true, Relaxed);
15776        scan_thread.join().unwrap();
15777        update_thread.join().unwrap();
15778        assert!(remaining_loops > 0, "test timed out");
15779    }
15780
15781    #[test]
15782    fn test_store_scan_consistency_unrooted() {
15783        for accounts_db_caching_enabled in &[false, true] {
15784            let (pruned_banks_sender, pruned_banks_receiver) = unbounded();
15785            let abs_request_handler = AbsRequestHandler {
15786                snapshot_request_handler: None,
15787                pruned_banks_receiver,
15788            };
15789            test_store_scan_consistency(
15790                *accounts_db_caching_enabled,
15791                move |bank0,
15792                      bank_to_scan_sender,
15793                      _scan_finished_receiver,
15794                      pubkeys_to_modify,
15795                      program_id,
15796                      starting_lamports| {
15797                    let mut current_major_fork_bank = bank0;
15798                    loop {
15799                        let mut current_minor_fork_bank = current_major_fork_bank.clone();
15800                        let num_new_banks = 2;
15801                        let lamports = current_minor_fork_bank.slot() + starting_lamports + 1;
15802                        // Modify banks on the two banks on the minor fork
15803                        for pubkeys_to_modify in &pubkeys_to_modify
15804                            .iter()
15805                            .chunks(pubkeys_to_modify.len() / num_new_banks)
15806                        {
15807                            current_minor_fork_bank = Arc::new(Bank::new_from_parent(
15808                                &current_minor_fork_bank,
15809                                &solana_sdk::pubkey::new_rand(),
15810                                current_minor_fork_bank.slot() + 2,
15811                            ));
15812                            let account = AccountSharedData::new(lamports, 0, &program_id);
15813                            // Write partial updates to each of the banks in the minor fork so if any of them
15814                            // get cleaned up, there will be keys with the wrong account value/missing.
15815                            for key in pubkeys_to_modify {
15816                                current_minor_fork_bank.store_account(key, &account);
15817                            }
15818                            current_minor_fork_bank.freeze();
15819                        }
15820
15821                        // All the parent banks made in this iteration of the loop
15822                        // are currently discoverable, previous parents should have
15823                        // been squashed
15824                        assert_eq!(
15825                            current_minor_fork_bank.clone().parents_inclusive().len(),
15826                            num_new_banks + 1,
15827                        );
15828
15829                        // `next_major_bank` needs to be sandwiched between the minor fork banks
15830                        // That way, after the squash(), the minor fork has the potential to see a
15831                        // *partial* clean of the banks < `next_major_bank`.
15832                        current_major_fork_bank = Arc::new(Bank::new_from_parent(
15833                            &current_major_fork_bank,
15834                            &solana_sdk::pubkey::new_rand(),
15835                            current_minor_fork_bank.slot() - 1,
15836                        ));
15837                        let lamports = current_major_fork_bank.slot() + starting_lamports + 1;
15838                        let account = AccountSharedData::new(lamports, 0, &program_id);
15839                        for key in pubkeys_to_modify.iter() {
15840                            // Store rooted updates to these pubkeys such that the minor
15841                            // fork updates to the same keys will be deleted by clean
15842                            current_major_fork_bank.store_account(key, &account);
15843                        }
15844
15845                        // Send the last new bank to the scan thread to perform the scan.
15846                        // Meanwhile this thread will continually set roots on a separate fork
15847                        // and squash/clean, purging the account entries from the minor forks
15848                        /*
15849                                    bank 0
15850                                /         \
15851                        minor bank 1       \
15852                            /         current_major_fork_bank
15853                        minor bank 2
15854
15855                        */
15856                        // The capacity of the channel is 1 so that this thread will wait for the scan to finish before starting
15857                        // the next iteration, allowing the scan to stay in sync with these updates
15858                        // such that every scan will see this interruption.
15859                        if bank_to_scan_sender.send(current_minor_fork_bank).is_err() {
15860                            // Channel was disconnected, exit
15861                            return;
15862                        }
15863                        current_major_fork_bank.freeze();
15864                        current_major_fork_bank.squash();
15865                        // Try to get cache flush/clean to overlap with the scan
15866                        current_major_fork_bank.force_flush_accounts_cache();
15867                        current_major_fork_bank.clean_accounts(false, false, None);
15868                        // Move purge here so that Bank::drop()->purge_slots() doesn't race
15869                        // with clean. Simulates the call from AccountsBackgroundService
15870                        abs_request_handler.handle_pruned_banks(&current_major_fork_bank, true);
15871                    }
15872                },
15873                Some(Box::new(SendDroppedBankCallback::new(
15874                    pruned_banks_sender.clone(),
15875                ))),
15876                AcceptableScanResults::NoFailure,
15877            )
15878        }
15879    }
15880
15881    #[test]
15882    fn test_store_scan_consistency_root() {
15883        for accounts_db_caching_enabled in &[false, true] {
15884            test_store_scan_consistency(
15885                *accounts_db_caching_enabled,
15886                |bank0,
15887                 bank_to_scan_sender,
15888                 _scan_finished_receiver,
15889                 pubkeys_to_modify,
15890                 program_id,
15891                 starting_lamports| {
15892                    let mut current_bank = bank0.clone();
15893                    let mut prev_bank = bank0;
15894                    loop {
15895                        let lamports_this_round = current_bank.slot() + starting_lamports + 1;
15896                        let account = AccountSharedData::new(lamports_this_round, 0, &program_id);
15897                        for key in pubkeys_to_modify.iter() {
15898                            current_bank.store_account(key, &account);
15899                        }
15900                        current_bank.freeze();
15901                        // Send the previous bank to the scan thread to perform the scan.
15902                        // Meanwhile this thread will squash and update roots immediately after
15903                        // so the roots will update while scanning.
15904                        //
15905                        // The capacity of the channel is 1 so that this thread will wait for the scan to finish before starting
15906                        // the next iteration, allowing the scan to stay in sync with these updates
15907                        // such that every scan will see this interruption.
15908                        if bank_to_scan_sender.send(prev_bank).is_err() {
15909                            // Channel was disconnected, exit
15910                            return;
15911                        }
15912                        current_bank.squash();
15913                        if current_bank.slot() % 2 == 0 {
15914                            current_bank.force_flush_accounts_cache();
15915                            current_bank.clean_accounts(true, false, None);
15916                        }
15917                        prev_bank = current_bank.clone();
15918                        current_bank = Arc::new(Bank::new_from_parent(
15919                            &current_bank,
15920                            &solana_sdk::pubkey::new_rand(),
15921                            current_bank.slot() + 1,
15922                        ));
15923                    }
15924                },
15925                None,
15926                AcceptableScanResults::NoFailure,
15927            );
15928        }
15929    }
15930
15931    fn setup_banks_on_fork_to_remove(
15932        bank0: Arc<Bank>,
15933        pubkeys_to_modify: Arc<HashSet<Pubkey>>,
15934        program_id: &Pubkey,
15935        starting_lamports: u64,
15936        num_banks_on_fork: usize,
15937        step_size: usize,
15938    ) -> (Arc<Bank>, Vec<(Slot, BankId)>, Ancestors) {
15939        // Need at least 2 keys to create inconsistency in account balances when deleting
15940        // slots
15941        assert!(pubkeys_to_modify.len() > 1);
15942
15943        // Tracks the bank at the tip of the to be created fork
15944        let mut bank_at_fork_tip = bank0;
15945
15946        // All the slots on the fork except slot 0
15947        let mut slots_on_fork = Vec::with_capacity(num_banks_on_fork);
15948
15949        // All accounts in each set of `step_size` slots will have the same account balances.
15950        // The account balances of the accounts changes every `step_size` banks. Thus if you
15951        // delete any one of the latest `step_size` slots, then you will see varying account
15952        // balances when loading the accounts.
15953        assert!(num_banks_on_fork >= 2);
15954        assert!(step_size >= 2);
15955        let pubkeys_to_modify: Vec<Pubkey> = pubkeys_to_modify.iter().cloned().collect();
15956        let pubkeys_to_modify_per_slot = (pubkeys_to_modify.len() / step_size).max(1);
15957        for _ in (0..num_banks_on_fork).step_by(step_size) {
15958            let mut lamports_this_round = 0;
15959            for i in 0..step_size {
15960                bank_at_fork_tip = Arc::new(Bank::new_from_parent(
15961                    &bank_at_fork_tip,
15962                    &solana_sdk::pubkey::new_rand(),
15963                    bank_at_fork_tip.slot() + 1,
15964                ));
15965                if lamports_this_round == 0 {
15966                    lamports_this_round = bank_at_fork_tip.bank_id() + starting_lamports + 1;
15967                }
15968                let pubkey_to_modify_starting_index = i * pubkeys_to_modify_per_slot;
15969                let account = AccountSharedData::new(lamports_this_round, 0, program_id);
15970                for pubkey_index_to_modify in pubkey_to_modify_starting_index
15971                    ..pubkey_to_modify_starting_index + pubkeys_to_modify_per_slot
15972                {
15973                    let key = pubkeys_to_modify[pubkey_index_to_modify % pubkeys_to_modify.len()];
15974                    bank_at_fork_tip.store_account(&key, &account);
15975                }
15976                bank_at_fork_tip.freeze();
15977                slots_on_fork.push((bank_at_fork_tip.slot(), bank_at_fork_tip.bank_id()));
15978            }
15979        }
15980
15981        let ancestors: Vec<(Slot, usize)> = slots_on_fork.iter().map(|(s, _)| (*s, 0)).collect();
15982        let ancestors = Ancestors::from(ancestors);
15983
15984        (bank_at_fork_tip, slots_on_fork, ancestors)
15985    }
15986
15987    #[test]
15988    fn test_remove_unrooted_before_scan() {
15989        for accounts_db_caching_enabled in &[false, true] {
15990            test_store_scan_consistency(
15991                *accounts_db_caching_enabled,
15992                |bank0,
15993                 bank_to_scan_sender,
15994                 scan_finished_receiver,
15995                 pubkeys_to_modify,
15996                 program_id,
15997                 starting_lamports| {
15998                    loop {
15999                        let (bank_at_fork_tip, slots_on_fork, ancestors) =
16000                            setup_banks_on_fork_to_remove(
16001                                bank0.clone(),
16002                                pubkeys_to_modify.clone(),
16003                                &program_id,
16004                                starting_lamports,
16005                                10,
16006                                2,
16007                            );
16008                        // Test removing the slot before the scan starts, should cause
16009                        // SlotRemoved error every time
16010                        for k in pubkeys_to_modify.iter() {
16011                            assert!(bank_at_fork_tip.load_slow(&ancestors, k).is_some());
16012                        }
16013                        bank_at_fork_tip.remove_unrooted_slots(&slots_on_fork);
16014
16015                        // Accounts on this fork should not be found after removal
16016                        for k in pubkeys_to_modify.iter() {
16017                            assert!(bank_at_fork_tip.load_slow(&ancestors, k).is_none());
16018                        }
16019                        if bank_to_scan_sender.send(bank_at_fork_tip.clone()).is_err() {
16020                            return;
16021                        }
16022
16023                        // Wait for scan to finish before starting next iteration
16024                        let finished_scan_bank_id = scan_finished_receiver.recv();
16025                        if finished_scan_bank_id.is_err() {
16026                            return;
16027                        }
16028                        assert_eq!(finished_scan_bank_id.unwrap(), bank_at_fork_tip.bank_id());
16029                    }
16030                },
16031                None,
16032                // Test removing the slot before the scan starts, should error every time
16033                AcceptableScanResults::DroppedSlotError,
16034            );
16035        }
16036    }
16037
16038    #[test]
16039    fn test_remove_unrooted_scan_then_recreate_same_slot_before_scan() {
16040        for accounts_db_caching_enabled in &[false, true] {
16041            test_store_scan_consistency(
16042                *accounts_db_caching_enabled,
16043                |bank0,
16044                 bank_to_scan_sender,
16045                 scan_finished_receiver,
16046                 pubkeys_to_modify,
16047                 program_id,
16048                 starting_lamports| {
16049                    let mut prev_bank = bank0.clone();
16050                    loop {
16051                        let start = Instant::now();
16052                        let (bank_at_fork_tip, slots_on_fork, ancestors) =
16053                            setup_banks_on_fork_to_remove(
16054                                bank0.clone(),
16055                                pubkeys_to_modify.clone(),
16056                                &program_id,
16057                                starting_lamports,
16058                                10,
16059                                2,
16060                            );
16061                        info!("setting up banks elapsed: {}", start.elapsed().as_millis());
16062                        // Remove the fork. Then we'll recreate the slots and only after we've
16063                        // recreated the slots, do we send this old bank for scanning.
16064                        // Skip scanning bank 0 on first iteration of loop, since those accounts
16065                        // aren't being removed
16066                        if prev_bank.slot() != 0 {
16067                            info!(
16068                                "sending bank with slot: {:?}, elapsed: {}",
16069                                prev_bank.slot(),
16070                                start.elapsed().as_millis()
16071                            );
16072                            // Although we dumped the slots last iteration via `remove_unrooted_slots()`,
16073                            // we've recreated those slots this iteration, so they should be findable
16074                            // again
16075                            for k in pubkeys_to_modify.iter() {
16076                                assert!(bank_at_fork_tip.load_slow(&ancestors, k).is_some());
16077                            }
16078
16079                            // Now after we've recreated the slots removed in the previous loop
16080                            // iteration, send the previous bank, should fail even though the
16081                            // same slots were recreated
16082                            if bank_to_scan_sender.send(prev_bank.clone()).is_err() {
16083                                return;
16084                            }
16085
16086                            let finished_scan_bank_id = scan_finished_receiver.recv();
16087                            if finished_scan_bank_id.is_err() {
16088                                return;
16089                            }
16090                            // Wait for scan to finish before starting next iteration
16091                            assert_eq!(finished_scan_bank_id.unwrap(), prev_bank.bank_id());
16092                        }
16093                        bank_at_fork_tip.remove_unrooted_slots(&slots_on_fork);
16094                        prev_bank = bank_at_fork_tip;
16095                    }
16096                },
16097                None,
16098                // Test removing the slot before the scan starts, should error every time
16099                AcceptableScanResults::DroppedSlotError,
16100            );
16101        }
16102    }
16103
16104    #[test]
16105    fn test_remove_unrooted_scan_interleaved_with_remove_unrooted_slots() {
16106        for accounts_db_caching_enabled in &[false, true] {
16107            test_store_scan_consistency(
16108                *accounts_db_caching_enabled,
16109                |bank0,
16110                 bank_to_scan_sender,
16111                 scan_finished_receiver,
16112                 pubkeys_to_modify,
16113                 program_id,
16114                 starting_lamports| {
16115                    loop {
16116                        let step_size = 2;
16117                        let (bank_at_fork_tip, slots_on_fork, ancestors) =
16118                            setup_banks_on_fork_to_remove(
16119                                bank0.clone(),
16120                                pubkeys_to_modify.clone(),
16121                                &program_id,
16122                                starting_lamports,
16123                                10,
16124                                step_size,
16125                            );
16126                        // Although we dumped the slots last iteration via `remove_unrooted_slots()`,
16127                        // we've recreated those slots this iteration, so they should be findable
16128                        // again
16129                        for k in pubkeys_to_modify.iter() {
16130                            assert!(bank_at_fork_tip.load_slow(&ancestors, k).is_some());
16131                        }
16132
16133                        // Now after we've recreated the slots removed in the previous loop
16134                        // iteration, send the previous bank, should fail even though the
16135                        // same slots were recreated
16136                        if bank_to_scan_sender.send(bank_at_fork_tip.clone()).is_err() {
16137                            return;
16138                        }
16139
16140                        // Remove 1 < `step_size` of the *latest* slots while the scan is happening.
16141                        // This should create inconsistency between the account balances of accounts
16142                        // stored in that slot, and the accounts stored in earlier slots
16143                        let slot_to_remove = *slots_on_fork.last().unwrap();
16144                        bank_at_fork_tip.remove_unrooted_slots(&[slot_to_remove]);
16145
16146                        // Wait for scan to finish before starting next iteration
16147                        let finished_scan_bank_id = scan_finished_receiver.recv();
16148                        if finished_scan_bank_id.is_err() {
16149                            return;
16150                        }
16151                        assert_eq!(finished_scan_bank_id.unwrap(), bank_at_fork_tip.bank_id());
16152
16153                        // Remove the rest of the slots before the next iteration
16154                        for (slot, bank_id) in slots_on_fork {
16155                            bank_at_fork_tip.remove_unrooted_slots(&[(slot, bank_id)]);
16156                        }
16157                    }
16158                },
16159                None,
16160                // Test removing the slot before the scan starts, should error every time
16161                AcceptableScanResults::Both,
16162            );
16163        }
16164    }
16165
16166    #[test]
16167    fn test_get_inflation_start_slot_devnet_testnet() {
16168        let GenesisConfigInfo {
16169            mut genesis_config, ..
16170        } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16171        genesis_config
16172            .accounts
16173            .remove(&feature_set::pico_inflation::id())
16174            .unwrap();
16175        genesis_config
16176            .accounts
16177            .remove(&feature_set::full_inflation::devnet_and_testnet::id())
16178            .unwrap();
16179        for pair in feature_set::FULL_INFLATION_FEATURE_PAIRS.iter() {
16180            genesis_config.accounts.remove(&pair.vote_id).unwrap();
16181            genesis_config.accounts.remove(&pair.enable_id).unwrap();
16182        }
16183
16184        let bank = Bank::new_for_tests(&genesis_config);
16185
16186        // Advance slot
16187        let mut bank = new_from_parent(&Arc::new(bank));
16188        bank = new_from_parent(&Arc::new(bank));
16189        assert_eq!(bank.get_inflation_start_slot(), 0);
16190        assert_eq!(bank.slot(), 2);
16191
16192        // Request `pico_inflation` activation
16193        bank.store_account(
16194            &feature_set::pico_inflation::id(),
16195            &feature::create_account(
16196                &Feature {
16197                    activated_at: Some(1),
16198                },
16199                42,
16200            ),
16201        );
16202        bank.compute_active_feature_set(true);
16203        assert_eq!(bank.get_inflation_start_slot(), 1);
16204
16205        // Advance slot
16206        bank = new_from_parent(&Arc::new(bank));
16207        assert_eq!(bank.slot(), 3);
16208
16209        // Request `full_inflation::devnet_and_testnet` activation,
16210        // which takes priority over pico_inflation
16211        bank.store_account(
16212            &feature_set::full_inflation::devnet_and_testnet::id(),
16213            &feature::create_account(
16214                &Feature {
16215                    activated_at: Some(2),
16216                },
16217                42,
16218            ),
16219        );
16220        bank.compute_active_feature_set(true);
16221        assert_eq!(bank.get_inflation_start_slot(), 2);
16222
16223        // Request `full_inflation::mainnet::certusone` activation,
16224        // which should have no effect on `get_inflation_start_slot`
16225        bank.store_account(
16226            &feature_set::full_inflation::mainnet::certusone::vote::id(),
16227            &feature::create_account(
16228                &Feature {
16229                    activated_at: Some(3),
16230                },
16231                42,
16232            ),
16233        );
16234        bank.store_account(
16235            &feature_set::full_inflation::mainnet::certusone::enable::id(),
16236            &feature::create_account(
16237                &Feature {
16238                    activated_at: Some(3),
16239                },
16240                42,
16241            ),
16242        );
16243        bank.compute_active_feature_set(true);
16244        assert_eq!(bank.get_inflation_start_slot(), 2);
16245    }
16246
16247    #[test]
16248    fn test_get_inflation_start_slot_mainnet() {
16249        let GenesisConfigInfo {
16250            mut genesis_config, ..
16251        } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16252        genesis_config
16253            .accounts
16254            .remove(&feature_set::pico_inflation::id())
16255            .unwrap();
16256        genesis_config
16257            .accounts
16258            .remove(&feature_set::full_inflation::devnet_and_testnet::id())
16259            .unwrap();
16260        for pair in feature_set::FULL_INFLATION_FEATURE_PAIRS.iter() {
16261            genesis_config.accounts.remove(&pair.vote_id).unwrap();
16262            genesis_config.accounts.remove(&pair.enable_id).unwrap();
16263        }
16264
16265        let bank = Bank::new_for_tests(&genesis_config);
16266
16267        // Advance slot
16268        let mut bank = new_from_parent(&Arc::new(bank));
16269        bank = new_from_parent(&Arc::new(bank));
16270        assert_eq!(bank.get_inflation_start_slot(), 0);
16271        assert_eq!(bank.slot(), 2);
16272
16273        // Request `pico_inflation` activation
16274        bank.store_account(
16275            &feature_set::pico_inflation::id(),
16276            &feature::create_account(
16277                &Feature {
16278                    activated_at: Some(1),
16279                },
16280                42,
16281            ),
16282        );
16283        bank.compute_active_feature_set(true);
16284        assert_eq!(bank.get_inflation_start_slot(), 1);
16285
16286        // Advance slot
16287        bank = new_from_parent(&Arc::new(bank));
16288        assert_eq!(bank.slot(), 3);
16289
16290        // Request `full_inflation::mainnet::certusone` activation,
16291        // which takes priority over pico_inflation
16292        bank.store_account(
16293            &feature_set::full_inflation::mainnet::certusone::vote::id(),
16294            &feature::create_account(
16295                &Feature {
16296                    activated_at: Some(2),
16297                },
16298                42,
16299            ),
16300        );
16301        bank.store_account(
16302            &feature_set::full_inflation::mainnet::certusone::enable::id(),
16303            &feature::create_account(
16304                &Feature {
16305                    activated_at: Some(2),
16306                },
16307                42,
16308            ),
16309        );
16310        bank.compute_active_feature_set(true);
16311        assert_eq!(bank.get_inflation_start_slot(), 2);
16312
16313        // Advance slot
16314        bank = new_from_parent(&Arc::new(bank));
16315        assert_eq!(bank.slot(), 4);
16316
16317        // Request `full_inflation::devnet_and_testnet` activation,
16318        // which should have no effect on `get_inflation_start_slot`
16319        bank.store_account(
16320            &feature_set::full_inflation::devnet_and_testnet::id(),
16321            &feature::create_account(
16322                &Feature {
16323                    activated_at: Some(bank.slot()),
16324                },
16325                42,
16326            ),
16327        );
16328        bank.compute_active_feature_set(true);
16329        assert_eq!(bank.get_inflation_start_slot(), 2);
16330    }
16331
16332    #[test]
16333    fn test_get_inflation_num_slots_with_activations() {
16334        let GenesisConfigInfo {
16335            mut genesis_config, ..
16336        } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16337        let slots_per_epoch = 32;
16338        genesis_config.epoch_schedule = EpochSchedule::new(slots_per_epoch);
16339        genesis_config
16340            .accounts
16341            .remove(&feature_set::pico_inflation::id())
16342            .unwrap();
16343        genesis_config
16344            .accounts
16345            .remove(&feature_set::full_inflation::devnet_and_testnet::id())
16346            .unwrap();
16347        for pair in feature_set::FULL_INFLATION_FEATURE_PAIRS.iter() {
16348            genesis_config.accounts.remove(&pair.vote_id).unwrap();
16349            genesis_config.accounts.remove(&pair.enable_id).unwrap();
16350        }
16351
16352        let mut bank = Bank::new_for_tests(&genesis_config);
16353        assert_eq!(bank.get_inflation_num_slots(), 0);
16354        for _ in 0..2 * slots_per_epoch {
16355            bank = new_from_parent(&Arc::new(bank));
16356        }
16357        assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
16358
16359        // Activate pico_inflation
16360        let pico_inflation_activation_slot = bank.slot();
16361        bank.store_account(
16362            &feature_set::pico_inflation::id(),
16363            &feature::create_account(
16364                &Feature {
16365                    activated_at: Some(pico_inflation_activation_slot),
16366                },
16367                42,
16368            ),
16369        );
16370        bank.compute_active_feature_set(true);
16371        assert_eq!(bank.get_inflation_num_slots(), slots_per_epoch);
16372        for _ in 0..slots_per_epoch {
16373            bank = new_from_parent(&Arc::new(bank));
16374        }
16375        assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
16376
16377        // Activate full_inflation::devnet_and_testnet
16378        let full_inflation_activation_slot = bank.slot();
16379        bank.store_account(
16380            &feature_set::full_inflation::devnet_and_testnet::id(),
16381            &feature::create_account(
16382                &Feature {
16383                    activated_at: Some(full_inflation_activation_slot),
16384                },
16385                42,
16386            ),
16387        );
16388        bank.compute_active_feature_set(true);
16389        assert_eq!(bank.get_inflation_num_slots(), slots_per_epoch);
16390        for _ in 0..slots_per_epoch {
16391            bank = new_from_parent(&Arc::new(bank));
16392        }
16393        assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
16394    }
16395
16396    #[test]
16397    fn test_get_inflation_num_slots_already_activated() {
16398        let GenesisConfigInfo {
16399            mut genesis_config, ..
16400        } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16401        let slots_per_epoch = 32;
16402        genesis_config.epoch_schedule = EpochSchedule::new(slots_per_epoch);
16403        let mut bank = Bank::new_for_tests(&genesis_config);
16404        assert_eq!(bank.get_inflation_num_slots(), 0);
16405        for _ in 0..slots_per_epoch {
16406            bank = new_from_parent(&Arc::new(bank));
16407        }
16408        assert_eq!(bank.get_inflation_num_slots(), slots_per_epoch);
16409        for _ in 0..slots_per_epoch {
16410            bank = new_from_parent(&Arc::new(bank));
16411        }
16412        assert_eq!(bank.get_inflation_num_slots(), 2 * slots_per_epoch);
16413    }
16414
16415    #[test]
16416    fn test_stake_vote_account_validity() {
16417        let thread_pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap();
16418        check_stake_vote_account_validity(
16419            true, // check owner change,
16420            |bank: &Bank| {
16421                bank.load_vote_and_stake_accounts_with_thread_pool(&thread_pool, null_tracer())
16422            },
16423        );
16424        // TODO: stakes cache should be hardened for the case when the account
16425        // owner is changed from vote/stake program to something else. see:
16426        // https://github.com/fair-exchange/safecoin/pull/24200#discussion_r849935444
16427        check_stake_vote_account_validity(
16428            false, // check owner change
16429            |bank: &Bank| bank.load_vote_and_stake_accounts(&thread_pool, null_tracer()),
16430        );
16431    }
16432
16433    fn check_stake_vote_account_validity<F>(
16434        check_owner_change: bool,
16435        load_vote_and_stake_accounts: F,
16436    ) where
16437        F: Fn(&Bank) -> LoadVoteAndStakeAccountsResult,
16438    {
16439        let validator_vote_keypairs0 = ValidatorVoteKeypairs::new_rand();
16440        let validator_vote_keypairs1 = ValidatorVoteKeypairs::new_rand();
16441        let validator_keypairs = vec![&validator_vote_keypairs0, &validator_vote_keypairs1];
16442        let GenesisConfigInfo { genesis_config, .. } = create_genesis_config_with_vote_accounts(
16443            1_000_000_000,
16444            &validator_keypairs,
16445            vec![LAMPORTS_PER_SAFE; 2],
16446        );
16447        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
16448        let vote_and_stake_accounts =
16449            load_vote_and_stake_accounts(&bank).vote_with_stake_delegations_map;
16450        assert_eq!(vote_and_stake_accounts.len(), 2);
16451
16452        let mut vote_account = bank
16453            .get_account(&validator_vote_keypairs0.vote_keypair.pubkey())
16454            .unwrap_or_default();
16455        let original_lamports = vote_account.lamports();
16456        vote_account.set_lamports(0);
16457        // Simulate vote account removal via full withdrawal
16458        bank.store_account(
16459            &validator_vote_keypairs0.vote_keypair.pubkey(),
16460            &vote_account,
16461        );
16462
16463        // Modify staked vote account owner; a vote account owned by another program could be
16464        // freely modified with malicious data
16465        let bogus_vote_program = Pubkey::new_unique();
16466        vote_account.set_lamports(original_lamports);
16467        vote_account.set_owner(bogus_vote_program);
16468        bank.store_account(
16469            &validator_vote_keypairs0.vote_keypair.pubkey(),
16470            &vote_account,
16471        );
16472
16473        assert_eq!(bank.vote_accounts().len(), 1);
16474
16475        // Modify stake account owner; a stake account owned by another program could be freely
16476        // modified with malicious data
16477        let bogus_stake_program = Pubkey::new_unique();
16478        let mut stake_account = bank
16479            .get_account(&validator_vote_keypairs1.stake_keypair.pubkey())
16480            .unwrap_or_default();
16481        stake_account.set_owner(bogus_stake_program);
16482        bank.store_account(
16483            &validator_vote_keypairs1.stake_keypair.pubkey(),
16484            &stake_account,
16485        );
16486
16487        // Accounts must be valid stake and vote accounts
16488        let vote_and_stake_accounts =
16489            load_vote_and_stake_accounts(&bank).vote_with_stake_delegations_map;
16490        assert_eq!(
16491            vote_and_stake_accounts.len(),
16492            usize::from(!check_owner_change)
16493        );
16494    }
16495
16496    #[test]
16497    fn test_vote_epoch_panic() {
16498        let GenesisConfigInfo {
16499            genesis_config,
16500            mint_keypair,
16501            ..
16502        } = create_genesis_config_with_leader(
16503            1_000_000_000_000_000,
16504            &Pubkey::new_unique(),
16505            bootstrap_validator_stake_lamports(),
16506        );
16507        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
16508
16509        let vote_keypair = keypair_from_seed(&[1u8; 32]).unwrap();
16510        let stake_keypair = keypair_from_seed(&[2u8; 32]).unwrap();
16511
16512        let mut setup_ixs = Vec::new();
16513        setup_ixs.extend(
16514            vote_instruction::create_account(
16515                &mint_keypair.pubkey(),
16516                &vote_keypair.pubkey(),
16517                &VoteInit {
16518                    node_pubkey: mint_keypair.pubkey(),
16519                    authorized_voter: vote_keypair.pubkey(),
16520                    authorized_withdrawer: mint_keypair.pubkey(),
16521                    commission: 0,
16522                },
16523                1_000_000_000,
16524            )
16525            .into_iter(),
16526        );
16527        setup_ixs.extend(
16528            stake_instruction::create_account_and_delegate_stake(
16529                &mint_keypair.pubkey(),
16530                &stake_keypair.pubkey(),
16531                &vote_keypair.pubkey(),
16532                &Authorized::auto(&mint_keypair.pubkey()),
16533                &Lockup::default(),
16534                1_000_000_000_000,
16535            )
16536            .into_iter(),
16537        );
16538        setup_ixs.push(vote_instruction::withdraw(
16539            &vote_keypair.pubkey(),
16540            &mint_keypair.pubkey(),
16541            1_000_000_000,
16542            &mint_keypair.pubkey(),
16543        ));
16544        setup_ixs.push(system_instruction::transfer(
16545            &mint_keypair.pubkey(),
16546            &vote_keypair.pubkey(),
16547            1_000_000_000,
16548        ));
16549
16550        let result = bank.process_transaction(&Transaction::new(
16551            &[&mint_keypair, &vote_keypair, &stake_keypair],
16552            Message::new(&setup_ixs, Some(&mint_keypair.pubkey())),
16553            bank.last_blockhash(),
16554        ));
16555        assert!(result.is_ok());
16556
16557        let _bank = Bank::new_from_parent(
16558            &bank,
16559            &mint_keypair.pubkey(),
16560            genesis_config.epoch_schedule.get_first_slot_in_epoch(1),
16561        );
16562    }
16563
16564    #[test]
16565    fn test_tx_log_order() {
16566        let GenesisConfigInfo {
16567            genesis_config,
16568            mint_keypair,
16569            ..
16570        } = create_genesis_config_with_leader(
16571            1_000_000_000_000_000,
16572            &Pubkey::new_unique(),
16573            bootstrap_validator_stake_lamports(),
16574        );
16575        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
16576        *bank.transaction_log_collector_config.write().unwrap() = TransactionLogCollectorConfig {
16577            mentioned_addresses: HashSet::new(),
16578            filter: TransactionLogCollectorFilter::All,
16579        };
16580        let blockhash = bank.last_blockhash();
16581
16582        let sender0 = Keypair::new();
16583        let sender1 = Keypair::new();
16584        bank.transfer(100, &mint_keypair, &sender0.pubkey())
16585            .unwrap();
16586        bank.transfer(100, &mint_keypair, &sender1.pubkey())
16587            .unwrap();
16588
16589        let recipient0 = Pubkey::new_unique();
16590        let recipient1 = Pubkey::new_unique();
16591        let tx0 = system_transaction::transfer(&sender0, &recipient0, 10, blockhash);
16592        let success_sig = tx0.signatures[0];
16593        let tx1 = system_transaction::transfer(&sender1, &recipient1, 110, blockhash); // Should produce insufficient funds log
16594        let failure_sig = tx1.signatures[0];
16595        let tx2 = system_transaction::transfer(&sender0, &recipient0, 1, blockhash);
16596        let txs = vec![tx0, tx1, tx2];
16597        let batch = bank.prepare_batch_for_tests(txs);
16598
16599        let execution_results = bank
16600            .load_execute_and_commit_transactions(
16601                &batch,
16602                MAX_PROCESSING_AGE,
16603                false,
16604                false,
16605                true,
16606                false,
16607                &mut ExecuteTimings::default(),
16608                None,
16609            )
16610            .0
16611            .execution_results;
16612
16613        assert_eq!(execution_results.len(), 3);
16614
16615        assert!(execution_results[0].details().is_some());
16616        assert!(execution_results[0]
16617            .details()
16618            .unwrap()
16619            .log_messages
16620            .as_ref()
16621            .unwrap()[1]
16622            .contains(&"success".to_string()));
16623        assert!(execution_results[1].details().is_some());
16624        assert!(execution_results[1]
16625            .details()
16626            .unwrap()
16627            .log_messages
16628            .as_ref()
16629            .unwrap()[2]
16630            .contains(&"failed".to_string()));
16631        assert!(!execution_results[2].was_executed());
16632
16633        let stored_logs = &bank.transaction_log_collector.read().unwrap().logs;
16634        let success_log_info = stored_logs
16635            .iter()
16636            .find(|transaction_log_info| transaction_log_info.signature == success_sig)
16637            .unwrap();
16638        assert!(success_log_info.result.is_ok());
16639        let success_log = success_log_info.log_messages.clone().pop().unwrap();
16640        assert!(success_log.contains(&"success".to_string()));
16641        let failure_log_info = stored_logs
16642            .iter()
16643            .find(|transaction_log_info| transaction_log_info.signature == failure_sig)
16644            .unwrap();
16645        assert!(failure_log_info.result.is_err());
16646        let failure_log = failure_log_info.log_messages.clone().pop().unwrap();
16647        assert!(failure_log.contains(&"failed".to_string()));
16648    }
16649
16650    #[test]
16651    fn test_tx_return_data() {
16652        solana_logger::setup();
16653        let GenesisConfigInfo {
16654            genesis_config,
16655            mint_keypair,
16656            ..
16657        } = create_genesis_config_with_leader(
16658            1_000_000_000_000_000,
16659            &Pubkey::new_unique(),
16660            bootstrap_validator_stake_lamports(),
16661        );
16662        let mut bank = Bank::new_for_tests(&genesis_config);
16663
16664        let mock_program_id = Pubkey::from([2u8; 32]);
16665        fn mock_process_instruction(
16666            _first_instruction_account: usize,
16667            invoke_context: &mut InvokeContext,
16668        ) -> result::Result<(), InstructionError> {
16669            let mock_program_id = Pubkey::from([2u8; 32]);
16670            let transaction_context = &mut invoke_context.transaction_context;
16671            let instruction_context = transaction_context.get_current_instruction_context()?;
16672            let instruction_data = instruction_context.get_instruction_data();
16673            let mut return_data = [0u8; MAX_RETURN_DATA];
16674            if !instruction_data.is_empty() {
16675                let index = usize::from_le_bytes(instruction_data.try_into().unwrap());
16676                return_data[index] = 1;
16677                transaction_context
16678                    .set_return_data(mock_program_id, return_data.to_vec())
16679                    .unwrap();
16680            }
16681            Ok(())
16682        }
16683        let blockhash = bank.last_blockhash();
16684        bank.add_builtin("mock_program", &mock_program_id, mock_process_instruction);
16685
16686        for index in [
16687            None,
16688            Some(0),
16689            Some(MAX_RETURN_DATA / 2),
16690            Some(MAX_RETURN_DATA - 1),
16691        ] {
16692            let data = if let Some(index) = index {
16693                usize::to_le_bytes(index).to_vec()
16694            } else {
16695                Vec::new()
16696            };
16697            let txs = vec![Transaction::new_signed_with_payer(
16698                &[Instruction {
16699                    program_id: mock_program_id,
16700                    data,
16701                    accounts: vec![AccountMeta::new(Pubkey::new_unique(), false)],
16702                }],
16703                Some(&mint_keypair.pubkey()),
16704                &[&mint_keypair],
16705                blockhash,
16706            )];
16707            let batch = bank.prepare_batch_for_tests(txs);
16708            let return_data = bank
16709                .load_execute_and_commit_transactions(
16710                    &batch,
16711                    MAX_PROCESSING_AGE,
16712                    false,
16713                    false,
16714                    false,
16715                    true,
16716                    &mut ExecuteTimings::default(),
16717                    None,
16718                )
16719                .0
16720                .execution_results[0]
16721                .details()
16722                .unwrap()
16723                .return_data
16724                .clone();
16725            if let Some(index) = index {
16726                let return_data = return_data.unwrap();
16727                assert_eq!(return_data.program_id, mock_program_id);
16728                let mut expected_data = vec![0u8; index];
16729                expected_data.push(1u8);
16730                assert_eq!(return_data.data, expected_data);
16731            } else {
16732                assert!(return_data.is_none());
16733            }
16734        }
16735    }
16736
16737    #[test]
16738    fn test_get_largest_accounts() {
16739        let GenesisConfigInfo { genesis_config, .. } =
16740            create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
16741        let bank = Bank::new_for_tests(&genesis_config);
16742
16743        let pubkeys: Vec<_> = (0..5).map(|_| Pubkey::new_unique()).collect();
16744        let pubkeys_hashset: HashSet<_> = pubkeys.iter().cloned().collect();
16745
16746        let pubkeys_balances: Vec<_> = pubkeys
16747            .iter()
16748            .cloned()
16749            .zip(vec![
16750                sol_to_lamports(2.0),
16751                sol_to_lamports(3.0),
16752                sol_to_lamports(3.0),
16753                sol_to_lamports(4.0),
16754                sol_to_lamports(5.0),
16755            ])
16756            .collect();
16757
16758        // Initialize accounts; all have larger SAFE balances than current Bank built-ins
16759        let account0 = AccountSharedData::new(pubkeys_balances[0].1, 0, &Pubkey::default());
16760        bank.store_account(&pubkeys_balances[0].0, &account0);
16761        let account1 = AccountSharedData::new(pubkeys_balances[1].1, 0, &Pubkey::default());
16762        bank.store_account(&pubkeys_balances[1].0, &account1);
16763        let account2 = AccountSharedData::new(pubkeys_balances[2].1, 0, &Pubkey::default());
16764        bank.store_account(&pubkeys_balances[2].0, &account2);
16765        let account3 = AccountSharedData::new(pubkeys_balances[3].1, 0, &Pubkey::default());
16766        bank.store_account(&pubkeys_balances[3].0, &account3);
16767        let account4 = AccountSharedData::new(pubkeys_balances[4].1, 0, &Pubkey::default());
16768        bank.store_account(&pubkeys_balances[4].0, &account4);
16769
16770        // Create HashSet to exclude an account
16771        let exclude4: HashSet<_> = pubkeys[4..].iter().cloned().collect();
16772
16773        let mut sorted_accounts = pubkeys_balances.clone();
16774        sorted_accounts.sort_by(|a, b| a.1.cmp(&b.1).reverse());
16775
16776        // Return only one largest account
16777        assert_eq!(
16778            bank.get_largest_accounts(1, &pubkeys_hashset, AccountAddressFilter::Include)
16779                .unwrap(),
16780            vec![(pubkeys[4], sol_to_lamports(5.0))]
16781        );
16782        assert_eq!(
16783            bank.get_largest_accounts(1, &HashSet::new(), AccountAddressFilter::Exclude)
16784                .unwrap(),
16785            vec![(pubkeys[4], sol_to_lamports(5.0))]
16786        );
16787        assert_eq!(
16788            bank.get_largest_accounts(1, &exclude4, AccountAddressFilter::Exclude)
16789                .unwrap(),
16790            vec![(pubkeys[3], sol_to_lamports(4.0))]
16791        );
16792
16793        // Return all added accounts
16794        let results = bank
16795            .get_largest_accounts(10, &pubkeys_hashset, AccountAddressFilter::Include)
16796            .unwrap();
16797        assert_eq!(results.len(), sorted_accounts.len());
16798        for pubkey_balance in sorted_accounts.iter() {
16799            assert!(results.contains(pubkey_balance));
16800        }
16801        let mut sorted_results = results.clone();
16802        sorted_results.sort_by(|a, b| a.1.cmp(&b.1).reverse());
16803        assert_eq!(sorted_results, results);
16804
16805        let expected_accounts = sorted_accounts[1..].to_vec();
16806        let results = bank
16807            .get_largest_accounts(10, &exclude4, AccountAddressFilter::Exclude)
16808            .unwrap();
16809        // results include 5 Bank builtins
16810        assert_eq!(results.len(), 10);
16811        for pubkey_balance in expected_accounts.iter() {
16812            assert!(results.contains(pubkey_balance));
16813        }
16814        let mut sorted_results = results.clone();
16815        sorted_results.sort_by(|a, b| a.1.cmp(&b.1).reverse());
16816        assert_eq!(sorted_results, results);
16817
16818        // Return 3 added accounts
16819        let expected_accounts = sorted_accounts[0..4].to_vec();
16820        let results = bank
16821            .get_largest_accounts(4, &pubkeys_hashset, AccountAddressFilter::Include)
16822            .unwrap();
16823        assert_eq!(results.len(), expected_accounts.len());
16824        for pubkey_balance in expected_accounts.iter() {
16825            assert!(results.contains(pubkey_balance));
16826        }
16827
16828        let expected_accounts = expected_accounts[1..4].to_vec();
16829        let results = bank
16830            .get_largest_accounts(3, &exclude4, AccountAddressFilter::Exclude)
16831            .unwrap();
16832        assert_eq!(results.len(), expected_accounts.len());
16833        for pubkey_balance in expected_accounts.iter() {
16834            assert!(results.contains(pubkey_balance));
16835        }
16836
16837        // Exclude more, and non-sequential, accounts
16838        let exclude: HashSet<_> = vec![pubkeys[0], pubkeys[2], pubkeys[4]]
16839            .iter()
16840            .cloned()
16841            .collect();
16842        assert_eq!(
16843            bank.get_largest_accounts(2, &exclude, AccountAddressFilter::Exclude)
16844                .unwrap(),
16845            vec![pubkeys_balances[3], pubkeys_balances[1]]
16846        );
16847    }
16848
16849    #[test]
16850    fn test_transfer_sysvar() {
16851        solana_logger::setup();
16852        let GenesisConfigInfo {
16853            genesis_config,
16854            mint_keypair,
16855            ..
16856        } = create_genesis_config_with_leader(
16857            1_000_000_000_000_000,
16858            &Pubkey::new_unique(),
16859            bootstrap_validator_stake_lamports(),
16860        );
16861        let mut bank = Bank::new_for_tests(&genesis_config);
16862
16863        fn mock_ix_processor(
16864            _first_instruction_account: usize,
16865            invoke_context: &mut InvokeContext,
16866        ) -> std::result::Result<(), InstructionError> {
16867            let transaction_context = &invoke_context.transaction_context;
16868            let instruction_context = transaction_context.get_current_instruction_context()?;
16869            instruction_context
16870                .try_borrow_instruction_account(transaction_context, 1)?
16871                .set_data(&[0; 40])?;
16872            Ok(())
16873        }
16874
16875        let program_id = solana_sdk::pubkey::new_rand();
16876        bank.add_builtin("mock_program1", &program_id, mock_ix_processor);
16877
16878        let blockhash = bank.last_blockhash();
16879        #[allow(deprecated)]
16880        let blockhash_sysvar = sysvar::clock::id();
16881        #[allow(deprecated)]
16882        let orig_lamports = bank.get_account(&sysvar::clock::id()).unwrap().lamports();
16883        let tx = system_transaction::transfer(&mint_keypair, &blockhash_sysvar, 10, blockhash);
16884        assert_eq!(
16885            bank.process_transaction(&tx),
16886            Err(TransactionError::InstructionError(
16887                0,
16888                InstructionError::ReadonlyLamportChange
16889            ))
16890        );
16891        assert_eq!(
16892            bank.get_account(&sysvar::clock::id()).unwrap().lamports(),
16893            orig_lamports
16894        );
16895
16896        let accounts = vec![
16897            AccountMeta::new(mint_keypair.pubkey(), true),
16898            AccountMeta::new(blockhash_sysvar, false),
16899        ];
16900        let ix = Instruction::new_with_bincode(program_id, &0, accounts);
16901        let message = Message::new(&[ix], Some(&mint_keypair.pubkey()));
16902        let tx = Transaction::new(&[&mint_keypair], message, blockhash);
16903        assert_eq!(
16904            bank.process_transaction(&tx),
16905            Err(TransactionError::InstructionError(
16906                0,
16907                InstructionError::ReadonlyDataModified
16908            ))
16909        );
16910    }
16911
16912    #[test]
16913    fn test_clean_dropped_unrooted_frozen_banks() {
16914        solana_logger::setup();
16915        do_test_clean_dropped_unrooted_banks(FreezeBank1::Yes);
16916    }
16917
16918    #[test]
16919    fn test_clean_dropped_unrooted_unfrozen_banks() {
16920        solana_logger::setup();
16921        do_test_clean_dropped_unrooted_banks(FreezeBank1::No);
16922    }
16923
16924    /// A simple enum to toggle freezing Bank1 or not.  Used in the clean_dropped_unrooted tests.
16925    enum FreezeBank1 {
16926        No,
16927        Yes,
16928    }
16929
16930    fn do_test_clean_dropped_unrooted_banks(freeze_bank1: FreezeBank1) {
16931        //! Test that dropped unrooted banks are cleaned up properly
16932        //!
16933        //! slot 0:       bank0 (rooted)
16934        //!               /   \
16935        //! slot 1:      /   bank1 (unrooted and dropped)
16936        //!             /
16937        //! slot 2:  bank2 (rooted)
16938        //!
16939        //! In the scenario above, when `clean_accounts()` is called on bank2, the keys that exist
16940        //! _only_ in bank1 should be cleaned up, since those keys are unreachable.
16941        //!
16942        //! The following scenarios are tested:
16943        //!
16944        //! 1. A key is written _only_ in an unrooted bank (key1)
16945        //!     - In this case, key1 should be cleaned up
16946        //! 2. A key is written in both an unrooted _and_ rooted bank (key3)
16947        //!     - In this case, key3's ref-count should be decremented correctly
16948        //! 3. A key with zero lamports is _only_ in an unrooted bank (key4)
16949        //!     - In this case, key4 should be cleaned up
16950        //! 4. A key with zero lamports is in both an unrooted _and_ rooted bank (key5)
16951        //!     - In this case, key5's ref-count should be decremented correctly
16952
16953        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
16954        let bank0 = Arc::new(Bank::new_for_tests(&genesis_config));
16955        let amount = genesis_config.rent.minimum_balance(0);
16956
16957        let collector = Pubkey::new_unique();
16958        let owner = Pubkey::new_unique();
16959
16960        let key1 = Keypair::new(); // only touched in bank1
16961        let key2 = Keypair::new(); // only touched in bank2
16962        let key3 = Keypair::new(); // touched in both bank1 and bank2
16963        let key4 = Keypair::new(); // in only bank1, and has zero lamports
16964        let key5 = Keypair::new(); // in both bank1 and bank2, and has zero lamports
16965        bank0
16966            .transfer(amount, &mint_keypair, &key2.pubkey())
16967            .unwrap();
16968        bank0.freeze();
16969
16970        let slot = 1;
16971        let bank1 = Bank::new_from_parent(&bank0, &collector, slot);
16972        bank1
16973            .transfer(amount, &mint_keypair, &key1.pubkey())
16974            .unwrap();
16975        bank1.store_account(&key4.pubkey(), &AccountSharedData::new(0, 0, &owner));
16976        bank1.store_account(&key5.pubkey(), &AccountSharedData::new(0, 0, &owner));
16977
16978        if let FreezeBank1::Yes = freeze_bank1 {
16979            bank1.freeze();
16980        }
16981
16982        let slot = slot + 1;
16983        let bank2 = Bank::new_from_parent(&bank0, &collector, slot);
16984        bank2
16985            .transfer(amount * 2, &mint_keypair, &key2.pubkey())
16986            .unwrap();
16987        bank2
16988            .transfer(amount, &mint_keypair, &key3.pubkey())
16989            .unwrap();
16990        bank2.store_account(&key5.pubkey(), &AccountSharedData::new(0, 0, &owner));
16991
16992        bank2.freeze(); // the freeze here is not strictly necessary, but more for illustration
16993        bank2.squash();
16994
16995        drop(bank1);
16996        bank2.clean_accounts(false, false, None);
16997
16998        let expected_ref_count_for_cleaned_up_keys = 0;
16999        let expected_ref_count_for_keys_in_both_slot1_and_slot2 = 1;
17000
17001        assert_eq!(
17002            bank2
17003                .rc
17004                .accounts
17005                .accounts_db
17006                .accounts_index
17007                .ref_count_from_storage(&key1.pubkey()),
17008            expected_ref_count_for_cleaned_up_keys
17009        );
17010        assert_ne!(
17011            bank2
17012                .rc
17013                .accounts
17014                .accounts_db
17015                .accounts_index
17016                .ref_count_from_storage(&key3.pubkey()),
17017            expected_ref_count_for_cleaned_up_keys
17018        );
17019        assert_eq!(
17020            bank2
17021                .rc
17022                .accounts
17023                .accounts_db
17024                .accounts_index
17025                .ref_count_from_storage(&key4.pubkey()),
17026            expected_ref_count_for_cleaned_up_keys
17027        );
17028        assert_eq!(
17029            bank2
17030                .rc
17031                .accounts
17032                .accounts_db
17033                .accounts_index
17034                .ref_count_from_storage(&key5.pubkey()),
17035            expected_ref_count_for_keys_in_both_slot1_and_slot2,
17036        );
17037
17038        assert_eq!(
17039            bank2.rc.accounts.accounts_db.alive_account_count_in_slot(1),
17040            0
17041        );
17042    }
17043
17044    #[test]
17045    fn test_rent_debits() {
17046        let mut rent_debits = RentDebits::default();
17047
17048        // No entry for 0 rewards
17049        rent_debits.insert(&Pubkey::new_unique(), 0, 0);
17050        assert_eq!(rent_debits.0.len(), 0);
17051
17052        // Some that actually work
17053        rent_debits.insert(&Pubkey::new_unique(), 1, 0);
17054        assert_eq!(rent_debits.0.len(), 1);
17055        rent_debits.insert(&Pubkey::new_unique(), i64::MAX as u64, 0);
17056        assert_eq!(rent_debits.0.len(), 2);
17057    }
17058
17059    #[test]
17060    fn test_compute_budget_program_noop() {
17061        solana_logger::setup();
17062        let GenesisConfigInfo {
17063            genesis_config,
17064            mint_keypair,
17065            ..
17066        } = create_genesis_config_with_leader(
17067            1_000_000_000_000_000,
17068            &Pubkey::new_unique(),
17069            bootstrap_validator_stake_lamports(),
17070        );
17071        let mut bank = Bank::new_for_tests(&genesis_config);
17072
17073        fn mock_ix_processor(
17074            _first_instruction_account: usize,
17075            invoke_context: &mut InvokeContext,
17076        ) -> std::result::Result<(), InstructionError> {
17077            let compute_budget = invoke_context.get_compute_budget();
17078            assert_eq!(
17079                *compute_budget,
17080                ComputeBudget {
17081                    compute_unit_limit: 1,
17082                    heap_size: Some(48 * 1024),
17083                    ..ComputeBudget::default()
17084                }
17085            );
17086            Ok(())
17087        }
17088        let program_id = solana_sdk::pubkey::new_rand();
17089        bank.add_builtin("mock_program", &program_id, mock_ix_processor);
17090
17091        let message = Message::new(
17092            &[
17093                ComputeBudgetInstruction::set_compute_unit_limit(1),
17094                ComputeBudgetInstruction::request_heap_frame(48 * 1024),
17095                Instruction::new_with_bincode(program_id, &0, vec![]),
17096            ],
17097            Some(&mint_keypair.pubkey()),
17098        );
17099        let tx = Transaction::new(&[&mint_keypair], message, bank.last_blockhash());
17100        bank.process_transaction(&tx).unwrap();
17101    }
17102
17103    #[test]
17104    fn test_compute_request_instruction() {
17105        solana_logger::setup();
17106        let GenesisConfigInfo {
17107            genesis_config,
17108            mint_keypair,
17109            ..
17110        } = create_genesis_config_with_leader(
17111            1_000_000_000_000_000,
17112            &Pubkey::new_unique(),
17113            bootstrap_validator_stake_lamports(),
17114        );
17115        let mut bank = Bank::new_for_tests(&genesis_config);
17116
17117        fn mock_ix_processor(
17118            _first_instruction_account: usize,
17119            invoke_context: &mut InvokeContext,
17120        ) -> std::result::Result<(), InstructionError> {
17121            let compute_budget = invoke_context.get_compute_budget();
17122            assert_eq!(
17123                *compute_budget,
17124                ComputeBudget {
17125                    compute_unit_limit: 1,
17126                    heap_size: Some(48 * 1024),
17127                    ..ComputeBudget::default()
17128                }
17129            );
17130            Ok(())
17131        }
17132        let program_id = solana_sdk::pubkey::new_rand();
17133        bank.add_builtin("mock_program", &program_id, mock_ix_processor);
17134
17135        let message = Message::new(
17136            &[
17137                ComputeBudgetInstruction::set_compute_unit_limit(1),
17138                ComputeBudgetInstruction::request_heap_frame(48 * 1024),
17139                Instruction::new_with_bincode(program_id, &0, vec![]),
17140            ],
17141            Some(&mint_keypair.pubkey()),
17142        );
17143        let tx = Transaction::new(&[&mint_keypair], message, bank.last_blockhash());
17144        bank.process_transaction(&tx).unwrap();
17145    }
17146
17147    #[test]
17148    fn test_failed_compute_request_instruction() {
17149        solana_logger::setup();
17150        let GenesisConfigInfo {
17151            genesis_config,
17152            mint_keypair,
17153            ..
17154        } = create_genesis_config_with_leader(
17155            1_000_000_000_000_000,
17156            &Pubkey::new_unique(),
17157            bootstrap_validator_stake_lamports(),
17158        );
17159        let mut bank = Bank::new_for_tests(&genesis_config);
17160
17161        let payer0_keypair = Keypair::new();
17162        let payer1_keypair = Keypair::new();
17163        bank.transfer(10, &mint_keypair, &payer0_keypair.pubkey())
17164            .unwrap();
17165        bank.transfer(10, &mint_keypair, &payer1_keypair.pubkey())
17166            .unwrap();
17167
17168        fn mock_ix_processor(
17169            _first_instruction_account: usize,
17170            invoke_context: &mut InvokeContext,
17171        ) -> std::result::Result<(), InstructionError> {
17172            let compute_budget = invoke_context.get_compute_budget();
17173            assert_eq!(
17174                *compute_budget,
17175                ComputeBudget {
17176                    compute_unit_limit: 1,
17177                    heap_size: Some(48 * 1024),
17178                    ..ComputeBudget::default()
17179                }
17180            );
17181            Ok(())
17182        }
17183        let program_id = solana_sdk::pubkey::new_rand();
17184        bank.add_builtin("mock_program", &program_id, mock_ix_processor);
17185
17186        // This message will not be executed because the compute budget request is invalid
17187        let message0 = Message::new(
17188            &[
17189                ComputeBudgetInstruction::request_heap_frame(1),
17190                Instruction::new_with_bincode(program_id, &0, vec![]),
17191            ],
17192            Some(&payer0_keypair.pubkey()),
17193        );
17194        // This message will be processed successfully
17195        let message1 = Message::new(
17196            &[
17197                ComputeBudgetInstruction::set_compute_unit_limit(1),
17198                ComputeBudgetInstruction::request_heap_frame(48 * 1024),
17199                Instruction::new_with_bincode(program_id, &0, vec![]),
17200            ],
17201            Some(&payer1_keypair.pubkey()),
17202        );
17203        let txs = vec![
17204            Transaction::new(&[&payer0_keypair], message0, bank.last_blockhash()),
17205            Transaction::new(&[&payer1_keypair], message1, bank.last_blockhash()),
17206        ];
17207        let results = bank.process_transactions(txs.iter());
17208
17209        assert_eq!(
17210            results[0],
17211            Err(TransactionError::InstructionError(
17212                0,
17213                InstructionError::InvalidInstructionData
17214            ))
17215        );
17216        assert_eq!(results[1], Ok(()));
17217        // two transfers and the mock program
17218        assert_eq!(bank.signature_count(), 3);
17219    }
17220
17221    #[test]
17222    fn test_verify_and_hash_transaction_sig_len() {
17223        let GenesisConfigInfo {
17224            mut genesis_config, ..
17225        } = create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
17226
17227        // activate all features but verify_tx_signatures_len
17228        activate_all_features(&mut genesis_config);
17229        genesis_config
17230            .accounts
17231            .remove(&feature_set::verify_tx_signatures_len::id());
17232        let bank = Bank::new_for_tests(&genesis_config);
17233
17234        let mut rng = rand::thread_rng();
17235        let recent_blockhash = hash::new_rand(&mut rng);
17236        let from_keypair = Keypair::new();
17237        let to_keypair = Keypair::new();
17238        let from_pubkey = from_keypair.pubkey();
17239        let to_pubkey = to_keypair.pubkey();
17240
17241        enum TestCase {
17242            AddSignature,
17243            RemoveSignature,
17244        }
17245
17246        let make_transaction = |case: TestCase| {
17247            let message = Message::new(
17248                &[system_instruction::transfer(&from_pubkey, &to_pubkey, 1)],
17249                Some(&from_pubkey),
17250            );
17251            let mut tx = Transaction::new(&[&from_keypair], message, recent_blockhash);
17252            assert_eq!(tx.message.header.num_required_signatures, 1);
17253            match case {
17254                TestCase::AddSignature => {
17255                    let signature = to_keypair.sign_message(&tx.message.serialize());
17256                    tx.signatures.push(signature);
17257                }
17258                TestCase::RemoveSignature => {
17259                    tx.signatures.remove(0);
17260                }
17261            }
17262            tx
17263        };
17264
17265        // Too few signatures: Sanitization failure
17266        {
17267            let tx = make_transaction(TestCase::RemoveSignature);
17268            assert_eq!(
17269                bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17270                    .err(),
17271                Some(TransactionError::SanitizeFailure),
17272            );
17273        }
17274        // Too many signatures: Sanitization failure
17275        {
17276            let tx = make_transaction(TestCase::AddSignature);
17277            assert_eq!(
17278                bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17279                    .err(),
17280                Some(TransactionError::SanitizeFailure),
17281            );
17282        }
17283    }
17284
17285    #[test]
17286    fn test_verify_transactions_packet_data_size() {
17287        let GenesisConfigInfo { genesis_config, .. } =
17288            create_genesis_config_with_leader(42, &solana_sdk::pubkey::new_rand(), 42);
17289        let bank = Bank::new_for_tests(&genesis_config);
17290
17291        let mut rng = rand::thread_rng();
17292        let recent_blockhash = hash::new_rand(&mut rng);
17293        let keypair = Keypair::new();
17294        let pubkey = keypair.pubkey();
17295        let make_transaction = |size| {
17296            let ixs: Vec<_> = std::iter::repeat_with(|| {
17297                system_instruction::transfer(&pubkey, &Pubkey::new_unique(), 1)
17298            })
17299            .take(size)
17300            .collect();
17301            let message = Message::new(&ixs[..], Some(&pubkey));
17302            Transaction::new(&[&keypair], message, recent_blockhash)
17303        };
17304        // Small transaction.
17305        {
17306            let tx = make_transaction(5);
17307            assert!(bincode::serialized_size(&tx).unwrap() <= PACKET_DATA_SIZE as u64);
17308            assert!(bank
17309                .verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17310                .is_ok(),);
17311        }
17312        // Big transaction.
17313        {
17314            let tx = make_transaction(25);
17315            assert!(bincode::serialized_size(&tx).unwrap() > PACKET_DATA_SIZE as u64);
17316            assert_eq!(
17317                bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17318                    .err(),
17319                Some(TransactionError::SanitizeFailure),
17320            );
17321        }
17322        // Assert that verify fails as soon as serialized
17323        // size exceeds packet data size.
17324        for size in 1..30 {
17325            let tx = make_transaction(size);
17326            assert_eq!(
17327                bincode::serialized_size(&tx).unwrap() <= PACKET_DATA_SIZE as u64,
17328                bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification)
17329                    .is_ok(),
17330            );
17331        }
17332    }
17333
17334    #[test]
17335    fn test_call_precomiled_program() {
17336        let GenesisConfigInfo {
17337            mut genesis_config,
17338            mint_keypair,
17339            ..
17340        } = create_genesis_config_with_leader(42, &Pubkey::new_unique(), 42);
17341        activate_all_features(&mut genesis_config);
17342        let bank = Bank::new_for_tests(&genesis_config);
17343
17344        // libsecp256k1
17345        let secp_privkey = libsecp256k1::SecretKey::random(&mut rand::thread_rng());
17346        let message_arr = b"hello";
17347        let instruction = solana_sdk::secp256k1_instruction::new_secp256k1_instruction(
17348            &secp_privkey,
17349            message_arr,
17350        );
17351        let tx = Transaction::new_signed_with_payer(
17352            &[instruction],
17353            Some(&mint_keypair.pubkey()),
17354            &[&mint_keypair],
17355            bank.last_blockhash(),
17356        );
17357        // calling the program should be successful when called from the bank
17358        // even if the program itself is not called
17359        bank.process_transaction(&tx).unwrap();
17360
17361        // ed25519
17362        let privkey = ed25519_dalek::Keypair::generate(&mut rand::thread_rng());
17363        let message_arr = b"hello";
17364        let instruction =
17365            solana_sdk::ed25519_instruction::new_ed25519_instruction(&privkey, message_arr);
17366        let tx = Transaction::new_signed_with_payer(
17367            &[instruction],
17368            Some(&mint_keypair.pubkey()),
17369            &[&mint_keypair],
17370            bank.last_blockhash(),
17371        );
17372        // calling the program should be successful when called from the bank
17373        // even if the program itself is not called
17374        bank.process_transaction(&tx).unwrap();
17375    }
17376
17377    #[test]
17378    fn test_calculate_fee() {
17379        // Default: no fee.
17380        let message =
17381            SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap();
17382        assert_eq!(
17383            Bank::calculate_fee(
17384                &message,
17385                0,
17386                &FeeStructure {
17387                    lamports_per_signature: 0,
17388                    ..FeeStructure::default()
17389                },
17390                true,
17391                true,
17392                true,
17393            ),
17394            0
17395        );
17396
17397        // One signature, a fee.
17398        assert_eq!(
17399            Bank::calculate_fee(
17400                &message,
17401                1,
17402                &FeeStructure {
17403                    lamports_per_signature: 1,
17404                    ..FeeStructure::default()
17405                },
17406                true,
17407                true,
17408                true,
17409            ),
17410            1
17411        );
17412
17413        // Two signatures, double the fee.
17414        let key0 = Pubkey::new_unique();
17415        let key1 = Pubkey::new_unique();
17416        let ix0 = system_instruction::transfer(&key0, &key1, 1);
17417        let ix1 = system_instruction::transfer(&key1, &key0, 1);
17418        let message = SanitizedMessage::try_from(Message::new(&[ix0, ix1], Some(&key0))).unwrap();
17419        assert_eq!(
17420            Bank::calculate_fee(
17421                &message,
17422                2,
17423                &FeeStructure {
17424                    lamports_per_signature: 2,
17425                    ..FeeStructure::default()
17426                },
17427                true,
17428                true,
17429                true,
17430            ),
17431            4
17432        );
17433    }
17434
17435    #[test]
17436    fn test_calculate_fee_compute_units() {
17437        let fee_structure = FeeStructure {
17438            lamports_per_signature: 1,
17439            ..FeeStructure::default()
17440        };
17441        let max_fee = fee_structure.compute_fee_bins.last().unwrap().fee;
17442        let lamports_per_signature = fee_structure.lamports_per_signature;
17443
17444        // One signature, no unit request
17445
17446        let message =
17447            SanitizedMessage::try_from(Message::new(&[], Some(&Pubkey::new_unique()))).unwrap();
17448        assert_eq!(
17449            Bank::calculate_fee(&message, 1, &fee_structure, true, true, true),
17450            max_fee + lamports_per_signature
17451        );
17452
17453        // Three signatures, two instructions, no unit request
17454
17455        let ix0 = system_instruction::transfer(&Pubkey::new_unique(), &Pubkey::new_unique(), 1);
17456        let ix1 = system_instruction::transfer(&Pubkey::new_unique(), &Pubkey::new_unique(), 1);
17457        let message =
17458            SanitizedMessage::try_from(Message::new(&[ix0, ix1], Some(&Pubkey::new_unique())))
17459                .unwrap();
17460        assert_eq!(
17461            Bank::calculate_fee(&message, 1, &fee_structure, true, true, true),
17462            max_fee + 3 * lamports_per_signature
17463        );
17464
17465        // Explicit fee schedule
17466
17467        for requested_compute_units in [
17468            0,
17469            5_000,
17470            10_000,
17471            100_000,
17472            300_000,
17473            500_000,
17474            700_000,
17475            900_000,
17476            1_100_000,
17477            1_300_000,
17478            MAX_COMPUTE_UNIT_LIMIT,
17479        ] {
17480            const PRIORITIZATION_FEE_RATE: u64 = 42;
17481            let prioritization_fee_details = PrioritizationFeeDetails::new(
17482                PrioritizationFeeType::ComputeUnitPrice(PRIORITIZATION_FEE_RATE),
17483                requested_compute_units as u64,
17484            );
17485            let message = SanitizedMessage::try_from(Message::new(
17486                &[
17487                    ComputeBudgetInstruction::set_compute_unit_limit(requested_compute_units),
17488                    ComputeBudgetInstruction::set_compute_unit_price(PRIORITIZATION_FEE_RATE),
17489                    Instruction::new_with_bincode(Pubkey::new_unique(), &0_u8, vec![]),
17490                ],
17491                Some(&Pubkey::new_unique()),
17492            ))
17493            .unwrap();
17494            let fee = Bank::calculate_fee(&message, 1, &fee_structure, true, true, true);
17495            assert_eq!(
17496                fee,
17497                lamports_per_signature + prioritization_fee_details.get_fee()
17498            );
17499        }
17500    }
17501
17502    #[test]
17503    fn test_calculate_fee_secp256k1() {
17504        let fee_structure = FeeStructure {
17505            lamports_per_signature: 1,
17506            ..FeeStructure::default()
17507        };
17508        let key0 = Pubkey::new_unique();
17509        let key1 = Pubkey::new_unique();
17510        let ix0 = system_instruction::transfer(&key0, &key1, 1);
17511
17512        let mut secp_instruction1 = Instruction {
17513            program_id: secp256k1_program::id(),
17514            accounts: vec![],
17515            data: vec![],
17516        };
17517        let mut secp_instruction2 = Instruction {
17518            program_id: secp256k1_program::id(),
17519            accounts: vec![],
17520            data: vec![1],
17521        };
17522
17523        let message = SanitizedMessage::try_from(Message::new(
17524            &[
17525                ix0.clone(),
17526                secp_instruction1.clone(),
17527                secp_instruction2.clone(),
17528            ],
17529            Some(&key0),
17530        ))
17531        .unwrap();
17532        assert_eq!(
17533            Bank::calculate_fee(&message, 1, &fee_structure, true, true, true),
17534            2
17535        );
17536
17537        secp_instruction1.data = vec![0];
17538        secp_instruction2.data = vec![10];
17539        let message = SanitizedMessage::try_from(Message::new(
17540            &[ix0, secp_instruction1, secp_instruction2],
17541            Some(&key0),
17542        ))
17543        .unwrap();
17544        assert_eq!(
17545            Bank::calculate_fee(&message, 1, &fee_structure, true, true, true),
17546            11
17547        );
17548    }
17549
17550    #[test]
17551    fn test_an_empty_instruction_without_program() {
17552        let (genesis_config, mint_keypair) = create_genesis_config(1);
17553        let destination = solana_sdk::pubkey::new_rand();
17554        let mut ix = system_instruction::transfer(&mint_keypair.pubkey(), &destination, 0);
17555        ix.program_id = native_loader::id(); // Empty executable account chain
17556        let message = Message::new(&[ix], Some(&mint_keypair.pubkey()));
17557        let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash());
17558
17559        let bank = Bank::new_for_tests(&genesis_config);
17560        assert_eq!(
17561            bank.process_transaction(&tx).unwrap_err(),
17562            TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId),
17563        );
17564    }
17565
17566    #[test]
17567    fn test_transaction_log_collector_get_logs_for_address() {
17568        let address = Pubkey::new_unique();
17569        let mut mentioned_address_map = HashMap::new();
17570        mentioned_address_map.insert(address, vec![0]);
17571        let transaction_log_collector = TransactionLogCollector {
17572            mentioned_address_map,
17573            ..TransactionLogCollector::default()
17574        };
17575        assert_eq!(
17576            transaction_log_collector.get_logs_for_address(Some(&address)),
17577            Some(Vec::<TransactionLogInfo>::new()),
17578        );
17579    }
17580
17581    /// Test exceeding the max accounts data size by creating accounts in a loop
17582    #[test]
17583    fn test_max_accounts_data_size_exceeded() {
17584        const NUM_ACCOUNTS: u64 = 20;
17585        const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH / (NUM_ACCOUNTS + 1);
17586        const REMAINING_ACCOUNTS_DATA_SIZE: u64 = NUM_ACCOUNTS * ACCOUNT_SIZE;
17587
17588        let (genesis_config, mint_keypair) = create_genesis_config(1_000_000_000_000);
17589        let mut bank = Bank::new_for_tests(&genesis_config);
17590        bank.activate_feature(&feature_set::cap_accounts_data_len::id());
17591        bank.accounts_data_size_initial = bank.accounts_data_size_limit()
17592            - REMAINING_ACCOUNTS_DATA_SIZE
17593            - bank.load_accounts_data_size_delta() as u64;
17594
17595        let mut i = 0;
17596        let result = loop {
17597            let txn = system_transaction::create_account(
17598                &mint_keypair,
17599                &Keypair::new(),
17600                bank.last_blockhash(),
17601                genesis_config
17602                    .rent
17603                    .minimum_balance(ACCOUNT_SIZE.try_into().unwrap()),
17604                ACCOUNT_SIZE,
17605                &solana_sdk::system_program::id(),
17606            );
17607
17608            let accounts_data_size_before = bank.load_accounts_data_size();
17609            let result = bank.process_transaction(&txn);
17610            let accounts_data_size_after = bank.load_accounts_data_size();
17611            assert!(accounts_data_size_after <= bank.accounts_data_size_limit());
17612            if result.is_err() {
17613                assert_eq!(i, NUM_ACCOUNTS);
17614                break result;
17615            }
17616
17617            assert_eq!(
17618                accounts_data_size_after - accounts_data_size_before,
17619                ACCOUNT_SIZE,
17620            );
17621            assert!(
17622                i <= NUM_ACCOUNTS,
17623                "test must complete within bounded limits"
17624            );
17625            i += 1;
17626        };
17627
17628        assert!(matches!(
17629            result,
17630            Err(TransactionError::InstructionError(
17631                _,
17632                solana_sdk::instruction::InstructionError::MaxAccountsDataSizeExceeded,
17633            ))
17634        ));
17635    }
17636
17637    /// Test processing a good transaction correctly modifies the accounts data size
17638    #[test]
17639    fn test_accounts_data_size_with_good_transaction() {
17640        const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH;
17641        let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1_000.));
17642        let mut bank = Bank::new_for_tests(&genesis_config);
17643        bank.activate_feature(&feature_set::cap_accounts_data_len::id());
17644        let transaction = system_transaction::create_account(
17645            &mint_keypair,
17646            &Keypair::new(),
17647            bank.last_blockhash(),
17648            genesis_config
17649                .rent
17650                .minimum_balance(ACCOUNT_SIZE.try_into().unwrap()),
17651            ACCOUNT_SIZE,
17652            &solana_sdk::system_program::id(),
17653        );
17654
17655        let accounts_data_size_before = bank.load_accounts_data_size();
17656        let accounts_data_size_delta_before = bank.load_accounts_data_size_delta();
17657        let accounts_data_size_delta_on_chain_before =
17658            bank.load_accounts_data_size_delta_on_chain();
17659        let result = bank.process_transaction(&transaction);
17660        let accounts_data_size_after = bank.load_accounts_data_size();
17661        let accounts_data_size_delta_after = bank.load_accounts_data_size_delta();
17662        let accounts_data_size_delta_on_chain_after = bank.load_accounts_data_size_delta_on_chain();
17663
17664        assert!(result.is_ok());
17665        assert_eq!(
17666            accounts_data_size_after - accounts_data_size_before,
17667            ACCOUNT_SIZE,
17668        );
17669        assert_eq!(
17670            accounts_data_size_delta_after - accounts_data_size_delta_before,
17671            ACCOUNT_SIZE as i64,
17672        );
17673        assert_eq!(
17674            accounts_data_size_delta_on_chain_after - accounts_data_size_delta_on_chain_before,
17675            ACCOUNT_SIZE as i64,
17676        );
17677    }
17678
17679    /// Test processing a bad transaction correctly modifies the accounts data size
17680    #[test]
17681    fn test_accounts_data_size_with_bad_transaction() {
17682        const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH;
17683        let mut bank = create_simple_test_bank(1_000_000_000_000);
17684        bank.activate_feature(&feature_set::cap_accounts_data_len::id());
17685        let transaction = system_transaction::create_account(
17686            &Keypair::new(),
17687            &Keypair::new(),
17688            bank.last_blockhash(),
17689            LAMPORTS_PER_SAFE,
17690            ACCOUNT_SIZE,
17691            &solana_sdk::system_program::id(),
17692        );
17693
17694        let accounts_data_size_before = bank.load_accounts_data_size();
17695        let accounts_data_size_delta_before = bank.load_accounts_data_size_delta();
17696        let accounts_data_size_delta_on_chain_before =
17697            bank.load_accounts_data_size_delta_on_chain();
17698        let result = bank.process_transaction(&transaction);
17699        let accounts_data_size_after = bank.load_accounts_data_size();
17700        let accounts_data_size_delta_after = bank.load_accounts_data_size_delta();
17701        let accounts_data_size_delta_on_chain_after = bank.load_accounts_data_size_delta_on_chain();
17702
17703        assert!(result.is_err());
17704        assert_eq!(accounts_data_size_after, accounts_data_size_before,);
17705        assert_eq!(
17706            accounts_data_size_delta_after,
17707            accounts_data_size_delta_before,
17708        );
17709        assert_eq!(
17710            accounts_data_size_delta_on_chain_after,
17711            accounts_data_size_delta_on_chain_before,
17712        );
17713    }
17714
17715    #[derive(Serialize, Deserialize)]
17716    enum MockTransferInstruction {
17717        Transfer(u64),
17718    }
17719
17720    fn mock_transfer_process_instruction(
17721        _first_instruction_account: usize,
17722        invoke_context: &mut InvokeContext,
17723    ) -> result::Result<(), InstructionError> {
17724        let transaction_context = &invoke_context.transaction_context;
17725        let instruction_context = transaction_context.get_current_instruction_context()?;
17726        let instruction_data = instruction_context.get_instruction_data();
17727        if let Ok(instruction) = bincode::deserialize(instruction_data) {
17728            match instruction {
17729                MockTransferInstruction::Transfer(amount) => {
17730                    instruction_context
17731                        .try_borrow_instruction_account(transaction_context, 1)?
17732                        .checked_sub_lamports(amount)?;
17733                    instruction_context
17734                        .try_borrow_instruction_account(transaction_context, 2)?
17735                        .checked_add_lamports(amount)?;
17736                    Ok(())
17737                }
17738            }
17739        } else {
17740            Err(InstructionError::InvalidInstructionData)
17741        }
17742    }
17743
17744    fn create_mock_transfer(
17745        payer: &Keypair,
17746        from: &Keypair,
17747        to: &Keypair,
17748        amount: u64,
17749        mock_program_id: Pubkey,
17750        recent_blockhash: Hash,
17751    ) -> Transaction {
17752        let account_metas = vec![
17753            AccountMeta::new(payer.pubkey(), true),
17754            AccountMeta::new(from.pubkey(), true),
17755            AccountMeta::new(to.pubkey(), true),
17756        ];
17757        let transfer_instruction = Instruction::new_with_bincode(
17758            mock_program_id,
17759            &MockTransferInstruction::Transfer(amount),
17760            account_metas,
17761        );
17762        Transaction::new_signed_with_payer(
17763            &[transfer_instruction],
17764            Some(&payer.pubkey()),
17765            &[payer, from, to],
17766            recent_blockhash,
17767        )
17768    }
17769
17770    #[test]
17771    fn test_invalid_rent_state_changes_existing_accounts() {
17772        let GenesisConfigInfo {
17773            mut genesis_config,
17774            mint_keypair,
17775            ..
17776        } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
17777        genesis_config.rent = Rent::default();
17778
17779        let mock_program_id = Pubkey::new_unique();
17780        let account_data_size = 100;
17781        let rent_exempt_minimum = genesis_config.rent.minimum_balance(account_data_size);
17782
17783        // Create legacy accounts of various kinds
17784        let rent_paying_account = Keypair::new();
17785        genesis_config.accounts.insert(
17786            rent_paying_account.pubkey(),
17787            Account::new_rent_epoch(
17788                rent_exempt_minimum - 1,
17789                account_data_size,
17790                &mock_program_id,
17791                INITIAL_RENT_EPOCH + 1,
17792            ),
17793        );
17794        let rent_exempt_account = Keypair::new();
17795        genesis_config.accounts.insert(
17796            rent_exempt_account.pubkey(),
17797            Account::new_rent_epoch(
17798                rent_exempt_minimum,
17799                account_data_size,
17800                &mock_program_id,
17801                INITIAL_RENT_EPOCH + 1,
17802            ),
17803        );
17804
17805        let mut bank = Bank::new_for_tests(&genesis_config);
17806        bank.add_builtin(
17807            "mock_program",
17808            &mock_program_id,
17809            mock_transfer_process_instruction,
17810        );
17811        let recent_blockhash = bank.last_blockhash();
17812
17813        let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
17814            let account = bank.get_account(pubkey).unwrap();
17815            Rent::default().is_exempt(account.lamports(), account.data().len())
17816        };
17817
17818        // RentPaying account can be left as Uninitialized, in other RentPaying states, or RentExempt
17819        let tx = create_mock_transfer(
17820            &mint_keypair,        // payer
17821            &rent_paying_account, // from
17822            &mint_keypair,        // to
17823            1,
17824            mock_program_id,
17825            recent_blockhash,
17826        );
17827        let result = bank.process_transaction(&tx);
17828        assert!(result.is_ok());
17829        assert!(!check_account_is_rent_exempt(&rent_paying_account.pubkey()));
17830        let tx = create_mock_transfer(
17831            &mint_keypair,        // payer
17832            &rent_paying_account, // from
17833            &mint_keypair,        // to
17834            rent_exempt_minimum - 2,
17835            mock_program_id,
17836            recent_blockhash,
17837        );
17838        let result = bank.process_transaction(&tx);
17839        assert!(result.is_ok());
17840        assert!(bank.get_account(&rent_paying_account.pubkey()).is_none());
17841
17842        bank.store_account(
17843            // restore program-owned account
17844            &rent_paying_account.pubkey(),
17845            &AccountSharedData::new(rent_exempt_minimum - 1, account_data_size, &mock_program_id),
17846        );
17847        let result = bank.transfer(1, &mint_keypair, &rent_paying_account.pubkey());
17848        assert!(result.is_ok());
17849        assert!(check_account_is_rent_exempt(&rent_paying_account.pubkey()));
17850
17851        // RentExempt account can only remain RentExempt or be Uninitialized
17852        let tx = create_mock_transfer(
17853            &mint_keypair,        // payer
17854            &rent_exempt_account, // from
17855            &mint_keypair,        // to
17856            1,
17857            mock_program_id,
17858            recent_blockhash,
17859        );
17860        let result = bank.process_transaction(&tx);
17861        assert!(result.is_err());
17862        assert!(check_account_is_rent_exempt(&rent_exempt_account.pubkey()));
17863        let result = bank.transfer(1, &mint_keypair, &rent_exempt_account.pubkey());
17864        assert!(result.is_ok());
17865        assert!(check_account_is_rent_exempt(&rent_exempt_account.pubkey()));
17866        let tx = create_mock_transfer(
17867            &mint_keypair,        // payer
17868            &rent_exempt_account, // from
17869            &mint_keypair,        // to
17870            rent_exempt_minimum + 1,
17871            mock_program_id,
17872            recent_blockhash,
17873        );
17874        let result = bank.process_transaction(&tx);
17875        assert!(result.is_ok());
17876        assert!(bank.get_account(&rent_exempt_account.pubkey()).is_none());
17877    }
17878
17879    #[test]
17880    fn test_invalid_rent_state_changes_new_accounts() {
17881        let GenesisConfigInfo {
17882            mut genesis_config,
17883            mint_keypair,
17884            ..
17885        } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
17886        genesis_config.rent = Rent::default();
17887
17888        let mock_program_id = Pubkey::new_unique();
17889        let account_data_size = 100;
17890        let rent_exempt_minimum = genesis_config.rent.minimum_balance(account_data_size);
17891
17892        let mut bank = Bank::new_for_tests(&genesis_config);
17893        bank.add_builtin(
17894            "mock_program",
17895            &mock_program_id,
17896            mock_transfer_process_instruction,
17897        );
17898        let recent_blockhash = bank.last_blockhash();
17899
17900        let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
17901            let account = bank.get_account(pubkey).unwrap();
17902            Rent::default().is_exempt(account.lamports(), account.data().len())
17903        };
17904
17905        // Try to create RentPaying account
17906        let rent_paying_account = Keypair::new();
17907        let tx = system_transaction::create_account(
17908            &mint_keypair,
17909            &rent_paying_account,
17910            recent_blockhash,
17911            rent_exempt_minimum - 1,
17912            account_data_size as u64,
17913            &mock_program_id,
17914        );
17915        let result = bank.process_transaction(&tx);
17916        assert!(result.is_err());
17917        assert!(bank.get_account(&rent_paying_account.pubkey()).is_none());
17918
17919        // Try to create RentExempt account
17920        let rent_exempt_account = Keypair::new();
17921        let tx = system_transaction::create_account(
17922            &mint_keypair,
17923            &rent_exempt_account,
17924            recent_blockhash,
17925            rent_exempt_minimum,
17926            account_data_size as u64,
17927            &mock_program_id,
17928        );
17929        let result = bank.process_transaction(&tx);
17930        assert!(result.is_ok());
17931        assert!(check_account_is_rent_exempt(&rent_exempt_account.pubkey()));
17932    }
17933
17934    #[test]
17935    fn test_drained_created_account() {
17936        let GenesisConfigInfo {
17937            mut genesis_config,
17938            mint_keypair,
17939            ..
17940        } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
17941        genesis_config.rent = Rent::default();
17942        activate_all_features(&mut genesis_config);
17943
17944        let mock_program_id = Pubkey::new_unique();
17945        // small enough to not pay rent, thus bypassing the data clearing rent
17946        // mechanism
17947        let data_size_no_rent = 100;
17948        // large enough to pay rent, will have data cleared
17949        let data_size_rent = 10000;
17950        let lamports_to_transfer = 100;
17951
17952        // Create legacy accounts of various kinds
17953        let created_keypair = Keypair::new();
17954
17955        let mut bank = Bank::new_for_tests(&genesis_config);
17956        bank.add_builtin(
17957            "mock_program",
17958            &mock_program_id,
17959            mock_transfer_process_instruction,
17960        );
17961        let recent_blockhash = bank.last_blockhash();
17962
17963        // Create and drain a small data size account
17964        let create_instruction = system_instruction::create_account(
17965            &mint_keypair.pubkey(),
17966            &created_keypair.pubkey(),
17967            lamports_to_transfer,
17968            data_size_no_rent,
17969            &mock_program_id,
17970        );
17971        let account_metas = vec![
17972            AccountMeta::new(mint_keypair.pubkey(), true),
17973            AccountMeta::new(created_keypair.pubkey(), true),
17974            AccountMeta::new(mint_keypair.pubkey(), false),
17975        ];
17976        let transfer_from_instruction = Instruction::new_with_bincode(
17977            mock_program_id,
17978            &MockTransferInstruction::Transfer(lamports_to_transfer),
17979            account_metas,
17980        );
17981        let tx = Transaction::new_signed_with_payer(
17982            &[create_instruction, transfer_from_instruction],
17983            Some(&mint_keypair.pubkey()),
17984            &[&mint_keypair, &created_keypair],
17985            recent_blockhash,
17986        );
17987
17988        let result = bank.process_transaction(&tx);
17989        assert!(result.is_ok());
17990        // account data is not stored because of zero balance even though its
17991        // data wasn't cleared
17992        assert!(bank.get_account(&created_keypair.pubkey()).is_none());
17993
17994        // Create and drain a large data size account
17995        let create_instruction = system_instruction::create_account(
17996            &mint_keypair.pubkey(),
17997            &created_keypair.pubkey(),
17998            lamports_to_transfer,
17999            data_size_rent,
18000            &mock_program_id,
18001        );
18002        let account_metas = vec![
18003            AccountMeta::new(mint_keypair.pubkey(), true),
18004            AccountMeta::new(created_keypair.pubkey(), true),
18005            AccountMeta::new(mint_keypair.pubkey(), false),
18006        ];
18007        let transfer_from_instruction = Instruction::new_with_bincode(
18008            mock_program_id,
18009            &MockTransferInstruction::Transfer(lamports_to_transfer),
18010            account_metas,
18011        );
18012        let tx = Transaction::new_signed_with_payer(
18013            &[create_instruction, transfer_from_instruction],
18014            Some(&mint_keypair.pubkey()),
18015            &[&mint_keypair, &created_keypair],
18016            recent_blockhash,
18017        );
18018
18019        let result = bank.process_transaction(&tx);
18020        assert!(result.is_ok());
18021        // account data is not stored because of zero balance
18022        assert!(bank.get_account(&created_keypair.pubkey()).is_none());
18023    }
18024
18025    #[test]
18026    fn test_rent_state_changes_sysvars() {
18027        let GenesisConfigInfo {
18028            mut genesis_config,
18029            mint_keypair,
18030            ..
18031        } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
18032        genesis_config.rent = Rent::default();
18033
18034        let validator_pubkey = solana_sdk::pubkey::new_rand();
18035        let validator_stake_lamports = sol_to_lamports(1.);
18036        let validator_staking_keypair = Keypair::new();
18037        let validator_voting_keypair = Keypair::new();
18038
18039        let validator_vote_account = vote_state::create_account(
18040            &validator_voting_keypair.pubkey(),
18041            &validator_pubkey,
18042            0,
18043            validator_stake_lamports,
18044        );
18045
18046        let validator_stake_account = stake_state::create_account(
18047            &validator_staking_keypair.pubkey(),
18048            &validator_voting_keypair.pubkey(),
18049            &validator_vote_account,
18050            &genesis_config.rent,
18051            validator_stake_lamports,
18052        );
18053
18054        genesis_config.accounts.insert(
18055            validator_pubkey,
18056            Account::new(
18057                genesis_config.rent.minimum_balance(0),
18058                0,
18059                &system_program::id(),
18060            ),
18061        );
18062        genesis_config.accounts.insert(
18063            validator_staking_keypair.pubkey(),
18064            Account::from(validator_stake_account),
18065        );
18066        genesis_config.accounts.insert(
18067            validator_voting_keypair.pubkey(),
18068            Account::from(validator_vote_account),
18069        );
18070
18071        let bank = Bank::new_for_tests(&genesis_config);
18072
18073        // Ensure transactions with sysvars succeed, even though sysvars appear RentPaying by balance
18074        let tx = Transaction::new_signed_with_payer(
18075            &[stake_instruction::deactivate_stake(
18076                &validator_staking_keypair.pubkey(),
18077                &validator_staking_keypair.pubkey(),
18078            )],
18079            Some(&mint_keypair.pubkey()),
18080            &[&mint_keypair, &validator_staking_keypair],
18081            bank.last_blockhash(),
18082        );
18083        let result = bank.process_transaction(&tx);
18084        assert!(result.is_ok());
18085    }
18086
18087    #[test]
18088    fn test_invalid_rent_state_changes_fee_payer() {
18089        let GenesisConfigInfo {
18090            mut genesis_config,
18091            mint_keypair,
18092            ..
18093        } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
18094        genesis_config.rent = Rent::default();
18095        genesis_config.fee_rate_governor = FeeRateGovernor::new(
18096            solana_sdk::fee_calculator::DEFAULT_TARGET_LAMPORTS_PER_SIGNATURE,
18097            solana_sdk::fee_calculator::DEFAULT_TARGET_SIGNATURES_PER_SLOT,
18098        );
18099        let rent_exempt_minimum = genesis_config.rent.minimum_balance(0);
18100
18101        // Create legacy rent-paying System account
18102        let rent_paying_fee_payer = Keypair::new();
18103        genesis_config.accounts.insert(
18104            rent_paying_fee_payer.pubkey(),
18105            Account::new(rent_exempt_minimum - 1, 0, &system_program::id()),
18106        );
18107        // Create RentExempt recipient account
18108        let recipient = Pubkey::new_unique();
18109        genesis_config.accounts.insert(
18110            recipient,
18111            Account::new(rent_exempt_minimum, 0, &system_program::id()),
18112        );
18113
18114        let bank = Bank::new_for_tests(&genesis_config);
18115        let recent_blockhash = bank.last_blockhash();
18116
18117        let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
18118            let account = bank.get_account(pubkey).unwrap();
18119            Rent::default().is_exempt(account.lamports(), account.data().len())
18120        };
18121
18122        // Create just-rent-exempt fee-payer
18123        let rent_exempt_fee_payer = Keypair::new();
18124        bank.transfer(
18125            rent_exempt_minimum,
18126            &mint_keypair,
18127            &rent_exempt_fee_payer.pubkey(),
18128        )
18129        .unwrap();
18130
18131        // Dummy message to determine fee amount
18132        let dummy_message = SanitizedMessage::try_from(Message::new_with_blockhash(
18133            &[system_instruction::transfer(
18134                &rent_exempt_fee_payer.pubkey(),
18135                &recipient,
18136                sol_to_lamports(1.),
18137            )],
18138            Some(&rent_exempt_fee_payer.pubkey()),
18139            &recent_blockhash,
18140        ))
18141        .unwrap();
18142        let fee = bank.get_fee_for_message(&dummy_message).unwrap();
18143
18144        // RentPaying fee-payer can remain RentPaying
18145        let tx = Transaction::new(
18146            &[&rent_paying_fee_payer, &mint_keypair],
18147            Message::new(
18148                &[system_instruction::transfer(
18149                    &mint_keypair.pubkey(),
18150                    &recipient,
18151                    rent_exempt_minimum,
18152                )],
18153                Some(&rent_paying_fee_payer.pubkey()),
18154            ),
18155            recent_blockhash,
18156        );
18157        let result = bank.process_transaction(&tx);
18158        assert!(result.is_ok());
18159        assert!(!check_account_is_rent_exempt(
18160            &rent_paying_fee_payer.pubkey()
18161        ));
18162
18163        // RentPaying fee-payer can remain RentPaying on failed executed tx
18164        let sender = Keypair::new();
18165        let fee_payer_balance = bank.get_balance(&rent_paying_fee_payer.pubkey());
18166        let tx = Transaction::new(
18167            &[&rent_paying_fee_payer, &sender],
18168            Message::new(
18169                &[system_instruction::transfer(
18170                    &sender.pubkey(),
18171                    &recipient,
18172                    rent_exempt_minimum,
18173                )],
18174                Some(&rent_paying_fee_payer.pubkey()),
18175            ),
18176            recent_blockhash,
18177        );
18178        let result = bank.process_transaction(&tx);
18179        assert_eq!(
18180            result.unwrap_err(),
18181            TransactionError::InstructionError(0, InstructionError::Custom(1))
18182        );
18183        assert_ne!(
18184            fee_payer_balance,
18185            bank.get_balance(&rent_paying_fee_payer.pubkey())
18186        );
18187        assert!(!check_account_is_rent_exempt(
18188            &rent_paying_fee_payer.pubkey()
18189        ));
18190
18191        // RentPaying fee-payer can be emptied with fee and transaction
18192        let tx = Transaction::new(
18193            &[&rent_paying_fee_payer],
18194            Message::new(
18195                &[system_instruction::transfer(
18196                    &rent_paying_fee_payer.pubkey(),
18197                    &recipient,
18198                    bank.get_balance(&rent_paying_fee_payer.pubkey()) - fee,
18199                )],
18200                Some(&rent_paying_fee_payer.pubkey()),
18201            ),
18202            recent_blockhash,
18203        );
18204        let result = bank.process_transaction(&tx);
18205        assert!(result.is_ok());
18206        assert_eq!(0, bank.get_balance(&rent_paying_fee_payer.pubkey()));
18207
18208        // RentExempt fee-payer cannot become RentPaying from transaction fee
18209        let tx = Transaction::new(
18210            &[&rent_exempt_fee_payer, &mint_keypair],
18211            Message::new(
18212                &[system_instruction::transfer(
18213                    &mint_keypair.pubkey(),
18214                    &recipient,
18215                    rent_exempt_minimum,
18216                )],
18217                Some(&rent_exempt_fee_payer.pubkey()),
18218            ),
18219            recent_blockhash,
18220        );
18221        let result = bank.process_transaction(&tx);
18222        assert_eq!(
18223            result.unwrap_err(),
18224            TransactionError::InsufficientFundsForRent { account_index: 0 }
18225        );
18226        assert!(check_account_is_rent_exempt(
18227            &rent_exempt_fee_payer.pubkey()
18228        ));
18229
18230        // RentExempt fee-payer cannot become RentPaying via failed executed tx
18231        let tx = Transaction::new(
18232            &[&rent_exempt_fee_payer, &sender],
18233            Message::new(
18234                &[system_instruction::transfer(
18235                    &sender.pubkey(),
18236                    &recipient,
18237                    rent_exempt_minimum,
18238                )],
18239                Some(&rent_exempt_fee_payer.pubkey()),
18240            ),
18241            recent_blockhash,
18242        );
18243        let result = bank.process_transaction(&tx);
18244        assert_eq!(
18245            result.unwrap_err(),
18246            TransactionError::InsufficientFundsForRent { account_index: 0 }
18247        );
18248        assert!(check_account_is_rent_exempt(
18249            &rent_exempt_fee_payer.pubkey()
18250        ));
18251
18252        // For good measure, show that a RentExempt fee-payer that is also debited by a transaction
18253        // cannot become RentPaying by that debit, but can still be charged for the fee
18254        bank.transfer(fee, &mint_keypair, &rent_exempt_fee_payer.pubkey())
18255            .unwrap();
18256        let fee_payer_balance = bank.get_balance(&rent_exempt_fee_payer.pubkey());
18257        assert_eq!(fee_payer_balance, rent_exempt_minimum + fee);
18258        let tx = Transaction::new(
18259            &[&rent_exempt_fee_payer],
18260            Message::new(
18261                &[system_instruction::transfer(
18262                    &rent_exempt_fee_payer.pubkey(),
18263                    &recipient,
18264                    fee,
18265                )],
18266                Some(&rent_exempt_fee_payer.pubkey()),
18267            ),
18268            recent_blockhash,
18269        );
18270        let result = bank.process_transaction(&tx);
18271        assert_eq!(
18272            result.unwrap_err(),
18273            TransactionError::InsufficientFundsForRent { account_index: 0 }
18274        );
18275        assert_eq!(
18276            fee_payer_balance - fee,
18277            bank.get_balance(&rent_exempt_fee_payer.pubkey())
18278        );
18279        assert!(check_account_is_rent_exempt(
18280            &rent_exempt_fee_payer.pubkey()
18281        ));
18282
18283        // Also show that a RentExempt fee-payer can be completely emptied via fee and transaction
18284        bank.transfer(fee + 1, &mint_keypair, &rent_exempt_fee_payer.pubkey())
18285            .unwrap();
18286        assert!(bank.get_balance(&rent_exempt_fee_payer.pubkey()) > rent_exempt_minimum + fee);
18287        let tx = Transaction::new(
18288            &[&rent_exempt_fee_payer],
18289            Message::new(
18290                &[system_instruction::transfer(
18291                    &rent_exempt_fee_payer.pubkey(),
18292                    &recipient,
18293                    bank.get_balance(&rent_exempt_fee_payer.pubkey()) - fee,
18294                )],
18295                Some(&rent_exempt_fee_payer.pubkey()),
18296            ),
18297            recent_blockhash,
18298        );
18299        let result = bank.process_transaction(&tx);
18300        assert!(result.is_ok());
18301        assert_eq!(0, bank.get_balance(&rent_exempt_fee_payer.pubkey()));
18302
18303        // ... but not if the fee alone would make it RentPaying
18304        bank.transfer(
18305            rent_exempt_minimum + 1,
18306            &mint_keypair,
18307            &rent_exempt_fee_payer.pubkey(),
18308        )
18309        .unwrap();
18310        assert!(bank.get_balance(&rent_exempt_fee_payer.pubkey()) < rent_exempt_minimum + fee);
18311        let tx = Transaction::new(
18312            &[&rent_exempt_fee_payer],
18313            Message::new(
18314                &[system_instruction::transfer(
18315                    &rent_exempt_fee_payer.pubkey(),
18316                    &recipient,
18317                    bank.get_balance(&rent_exempt_fee_payer.pubkey()) - fee,
18318                )],
18319                Some(&rent_exempt_fee_payer.pubkey()),
18320            ),
18321            recent_blockhash,
18322        );
18323        let result = bank.process_transaction(&tx);
18324        assert_eq!(
18325            result.unwrap_err(),
18326            TransactionError::InsufficientFundsForRent { account_index: 0 }
18327        );
18328        assert!(check_account_is_rent_exempt(
18329            &rent_exempt_fee_payer.pubkey()
18330        ));
18331    }
18332
18333    // Ensure System transfers of any size can be made to the incinerator
18334    #[test]
18335    fn test_rent_state_incinerator() {
18336        let GenesisConfigInfo {
18337            mut genesis_config,
18338            mint_keypair,
18339            ..
18340        } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
18341        genesis_config.rent = Rent::default();
18342        let rent_exempt_minimum = genesis_config.rent.minimum_balance(0);
18343
18344        let bank = Bank::new_for_tests(&genesis_config);
18345
18346        for amount in [rent_exempt_minimum - 1, rent_exempt_minimum] {
18347            bank.transfer(amount, &mint_keypair, &solana_sdk::incinerator::id())
18348                .unwrap();
18349        }
18350    }
18351
18352    #[test]
18353    fn test_rent_state_list_len() {
18354        let GenesisConfigInfo {
18355            mut genesis_config,
18356            mint_keypair,
18357            ..
18358        } = create_genesis_config_with_leader(sol_to_lamports(100.), &Pubkey::new_unique(), 42);
18359        genesis_config.rent = Rent::default();
18360
18361        let bank = Bank::new_for_tests(&genesis_config);
18362        let recipient = Pubkey::new_unique();
18363        let tx = system_transaction::transfer(
18364            &mint_keypair,
18365            &recipient,
18366            sol_to_lamports(1.),
18367            bank.last_blockhash(),
18368        );
18369        let number_of_instructions_at_transaction_level = tx.message().instructions.len();
18370        let num_accounts = tx.message().account_keys.len();
18371        let sanitized_tx = SanitizedTransaction::try_from_legacy_transaction(tx).unwrap();
18372        let mut error_counters = TransactionErrorMetrics::default();
18373        let loaded_txs = bank.rc.accounts.load_accounts(
18374            &bank.ancestors,
18375            &[sanitized_tx.clone()],
18376            vec![(Ok(()), None)],
18377            &bank.blockhash_queue.read().unwrap(),
18378            &mut error_counters,
18379            &bank.rent_collector,
18380            &bank.feature_set,
18381            &FeeStructure::default(),
18382            None,
18383        );
18384
18385        let compute_budget = bank.compute_budget.unwrap_or_else(|| {
18386            ComputeBudget::new(compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64)
18387        });
18388        let transaction_context = TransactionContext::new(
18389            loaded_txs[0].0.as_ref().unwrap().accounts.clone(),
18390            Some(Rent::default()),
18391            compute_budget.max_invoke_depth.saturating_add(1),
18392            number_of_instructions_at_transaction_level,
18393        );
18394
18395        assert_eq!(
18396            bank.get_transaction_account_state_info(&transaction_context, sanitized_tx.message())
18397                .len(),
18398            num_accounts,
18399        );
18400    }
18401
18402    #[test]
18403    fn test_update_accounts_data_size() {
18404        // Test: Subtraction saturates at 0
18405        {
18406            let bank = create_simple_test_bank(100);
18407            let initial_data_size = bank.load_accounts_data_size() as i64;
18408            let data_size = 567;
18409            bank.accounts_data_size_delta_on_chain
18410                .store(data_size, Release);
18411            bank.update_accounts_data_size_delta_on_chain(
18412                (initial_data_size + data_size + 1).saturating_neg(),
18413            );
18414            assert_eq!(bank.load_accounts_data_size(), 0);
18415        }
18416
18417        // Test: Addition saturates at u64::MAX
18418        {
18419            let mut bank = create_simple_test_bank(100);
18420            let data_size_remaining = 567;
18421            bank.accounts_data_size_initial = u64::MAX - data_size_remaining;
18422            bank.accounts_data_size_delta_off_chain
18423                .store((data_size_remaining + 1) as i64, Release);
18424            assert_eq!(bank.load_accounts_data_size(), u64::MAX);
18425        }
18426
18427        // Test: Updates work as expected
18428        {
18429            // Set the accounts data size to be in the middle, then perform a bunch of small
18430            // updates, checking the results after each one.
18431            let mut bank = create_simple_test_bank(100);
18432            bank.accounts_data_size_initial = u32::MAX as u64;
18433            let mut rng = rand::thread_rng();
18434            for _ in 0..100 {
18435                let initial = bank.load_accounts_data_size() as i64;
18436                let delta1 = rng.gen_range(-500, 500);
18437                bank.update_accounts_data_size_delta_on_chain(delta1);
18438                let delta2 = rng.gen_range(-500, 500);
18439                bank.update_accounts_data_size_delta_off_chain(delta2);
18440                assert_eq!(
18441                    bank.load_accounts_data_size() as i64,
18442                    initial.saturating_add(delta1).saturating_add(delta2),
18443                );
18444            }
18445        }
18446    }
18447
18448    #[test]
18449    fn test_skip_rewrite() {
18450        solana_logger::setup();
18451        let mut account = AccountSharedData::default();
18452        let bank_slot = 10;
18453        for account_rent_epoch in 0..3 {
18454            account.set_rent_epoch(account_rent_epoch);
18455            for rent_amount in [0, 1] {
18456                for loaded_slot in (bank_slot - 1)..=bank_slot {
18457                    for old_rent_epoch in account_rent_epoch.saturating_sub(1)..=account_rent_epoch
18458                    {
18459                        let skip = Bank::skip_rewrite(
18460                            bank_slot,
18461                            rent_amount,
18462                            loaded_slot,
18463                            old_rent_epoch,
18464                            &account,
18465                        );
18466                        let mut should_skip = true;
18467                        if rent_amount != 0
18468                            || account_rent_epoch == 0
18469                            || (account_rent_epoch != old_rent_epoch && loaded_slot == bank_slot)
18470                        {
18471                            should_skip = false;
18472                        }
18473                        assert_eq!(
18474                            skip,
18475                            should_skip,
18476                            "{:?}",
18477                            (
18478                                account_rent_epoch,
18479                                old_rent_epoch,
18480                                rent_amount,
18481                                loaded_slot,
18482                                old_rent_epoch
18483                            )
18484                        );
18485                    }
18486                }
18487            }
18488        }
18489    }
18490
18491    #[test]
18492    fn test_remember_skipped_rewrites() {
18493        let GenesisConfigInfo {
18494            mut genesis_config, ..
18495        } = create_genesis_config_with_leader(1_000_000_000, &Pubkey::new_unique(), 42);
18496        genesis_config.rent = Rent::default();
18497        activate_all_features(&mut genesis_config);
18498
18499        let bank = Bank::new_for_tests(&genesis_config);
18500
18501        assert!(bank.rewrites_skipped_this_slot.read().unwrap().is_empty());
18502        bank.remember_skipped_rewrites(Vec::default());
18503        assert!(bank.rewrites_skipped_this_slot.read().unwrap().is_empty());
18504
18505        // bank's map is initially empty
18506        let mut test = vec![(Pubkey::from([4; 32]), Hash::new(&[5; 32]))];
18507        bank.remember_skipped_rewrites(test.clone());
18508        assert_eq!(
18509            *bank.rewrites_skipped_this_slot.read().unwrap(),
18510            test.clone().into_iter().collect()
18511        );
18512
18513        // now there is already some stuff in the bank's map
18514        test.push((Pubkey::from([6; 32]), Hash::new(&[7; 32])));
18515        bank.remember_skipped_rewrites(test[1..].to_vec());
18516        assert_eq!(
18517            *bank.rewrites_skipped_this_slot.read().unwrap(),
18518            test.clone().into_iter().collect()
18519        );
18520
18521        // all contents are already in map
18522        bank.remember_skipped_rewrites(test[1..].to_vec());
18523        assert_eq!(
18524            *bank.rewrites_skipped_this_slot.read().unwrap(),
18525            test.clone().into_iter().collect()
18526        );
18527
18528        // all contents are already in map, but we're changing hash values
18529        test[0].1 = Hash::new(&[8; 32]);
18530        test[1].1 = Hash::new(&[9; 32]);
18531        bank.remember_skipped_rewrites(test.to_vec());
18532        assert_eq!(
18533            *bank.rewrites_skipped_this_slot.read().unwrap(),
18534            test.into_iter().collect()
18535        );
18536    }
18537
18538    #[test]
18539    fn test_inner_instructions_list_from_instruction_trace() {
18540        let instruction_trace = vec![
18541            vec![
18542                InstructionContext::new(0, 0, &[], &[], &[1]),
18543                InstructionContext::new(1, 0, &[], &[], &[2]),
18544            ],
18545            vec![],
18546            vec![
18547                InstructionContext::new(0, 0, &[], &[], &[3]),
18548                InstructionContext::new(1, 0, &[], &[], &[4]),
18549                InstructionContext::new(2, 0, &[], &[], &[5]),
18550                InstructionContext::new(1, 0, &[], &[], &[6]),
18551            ],
18552        ];
18553
18554        let inner_instructions = inner_instructions_list_from_instruction_trace(&instruction_trace);
18555
18556        assert_eq!(
18557            inner_instructions,
18558            vec![
18559                vec![CompiledInstruction::new_from_raw_parts(0, vec![2], vec![])],
18560                vec![],
18561                vec![
18562                    CompiledInstruction::new_from_raw_parts(0, vec![4], vec![]),
18563                    CompiledInstruction::new_from_raw_parts(0, vec![5], vec![]),
18564                    CompiledInstruction::new_from_raw_parts(0, vec![6], vec![])
18565                ]
18566            ]
18567        );
18568    }
18569
18570    #[derive(Serialize, Deserialize)]
18571    enum MockReallocInstruction {
18572        Realloc(usize, u64, Pubkey),
18573    }
18574
18575    fn mock_realloc_process_instruction(
18576        _first_instruction_account: usize,
18577        invoke_context: &mut InvokeContext,
18578    ) -> result::Result<(), InstructionError> {
18579        let transaction_context = &invoke_context.transaction_context;
18580        let instruction_context = transaction_context.get_current_instruction_context()?;
18581        let instruction_data = instruction_context.get_instruction_data();
18582        if let Ok(instruction) = bincode::deserialize(instruction_data) {
18583            match instruction {
18584                MockReallocInstruction::Realloc(new_size, new_balance, _) => {
18585                    // Set data length
18586                    instruction_context
18587                        .try_borrow_instruction_account(transaction_context, 1)?
18588                        .set_data_length(new_size)?;
18589
18590                    // set balance
18591                    let current_balance = instruction_context
18592                        .try_borrow_instruction_account(transaction_context, 1)?
18593                        .get_lamports();
18594                    let diff_balance = (new_balance as i64).saturating_sub(current_balance as i64);
18595                    let amount = diff_balance.unsigned_abs();
18596                    if diff_balance.is_positive() {
18597                        instruction_context
18598                            .try_borrow_instruction_account(transaction_context, 0)?
18599                            .checked_sub_lamports(amount)?;
18600                        instruction_context
18601                            .try_borrow_instruction_account(transaction_context, 1)?
18602                            .set_lamports(new_balance)?;
18603                    } else {
18604                        instruction_context
18605                            .try_borrow_instruction_account(transaction_context, 0)?
18606                            .checked_add_lamports(amount)?;
18607                        instruction_context
18608                            .try_borrow_instruction_account(transaction_context, 1)?
18609                            .set_lamports(new_balance)?;
18610                    }
18611                    Ok(())
18612                }
18613            }
18614        } else {
18615            Err(InstructionError::InvalidInstructionData)
18616        }
18617    }
18618
18619    fn create_mock_realloc_tx(
18620        payer: &Keypair,
18621        funder: &Keypair,
18622        reallocd: &Pubkey,
18623        new_size: usize,
18624        new_balance: u64,
18625        mock_program_id: Pubkey,
18626        recent_blockhash: Hash,
18627    ) -> Transaction {
18628        let account_metas = vec![
18629            AccountMeta::new(funder.pubkey(), false),
18630            AccountMeta::new(*reallocd, false),
18631        ];
18632        let instruction = Instruction::new_with_bincode(
18633            mock_program_id,
18634            &MockReallocInstruction::Realloc(new_size, new_balance, Pubkey::new_unique()),
18635            account_metas,
18636        );
18637        Transaction::new_signed_with_payer(
18638            &[instruction],
18639            Some(&payer.pubkey()),
18640            &[payer],
18641            recent_blockhash,
18642        )
18643    }
18644
18645    #[test]
18646    fn test_resize_and_rent() {
18647        let GenesisConfigInfo {
18648            mut genesis_config,
18649            mint_keypair,
18650            ..
18651        } = create_genesis_config_with_leader(1_000_000_000, &Pubkey::new_unique(), 42);
18652        genesis_config.rent = Rent::default();
18653        activate_all_features(&mut genesis_config);
18654
18655        let mut bank = Bank::new_for_tests(&genesis_config);
18656
18657        let mock_program_id = Pubkey::new_unique();
18658        bank.add_builtin(
18659            "mock_realloc_program",
18660            &mock_program_id,
18661            mock_realloc_process_instruction,
18662        );
18663        let recent_blockhash = bank.last_blockhash();
18664
18665        let account_data_size_small = 1024;
18666        let rent_exempt_minimum_small =
18667            genesis_config.rent.minimum_balance(account_data_size_small);
18668        let account_data_size_large = 2048;
18669        let rent_exempt_minimum_large =
18670            genesis_config.rent.minimum_balance(account_data_size_large);
18671
18672        let funding_keypair = Keypair::new();
18673        bank.store_account(
18674            &funding_keypair.pubkey(),
18675            &AccountSharedData::new(1_000_000_000, 0, &mock_program_id),
18676        );
18677
18678        let rent_paying_pubkey = solana_sdk::pubkey::new_rand();
18679        let mut rent_paying_account = AccountSharedData::new(
18680            rent_exempt_minimum_small - 1,
18681            account_data_size_small,
18682            &mock_program_id,
18683        );
18684        rent_paying_account.set_rent_epoch(1);
18685
18686        // restore program-owned account
18687        bank.store_account(&rent_paying_pubkey, &rent_paying_account);
18688
18689        // rent paying, realloc larger, fail because not rent exempt
18690        let tx = create_mock_realloc_tx(
18691            &mint_keypair,
18692            &funding_keypair,
18693            &rent_paying_pubkey,
18694            account_data_size_large,
18695            rent_exempt_minimum_small - 1,
18696            mock_program_id,
18697            recent_blockhash,
18698        );
18699        let expected_err = {
18700            let account_index = tx
18701                .message
18702                .account_keys
18703                .iter()
18704                .position(|key| key == &rent_paying_pubkey)
18705                .unwrap() as u8;
18706            TransactionError::InsufficientFundsForRent { account_index }
18707        };
18708        assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18709        assert_eq!(
18710            rent_exempt_minimum_small - 1,
18711            bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18712        );
18713
18714        // rent paying, realloc larger and rent exempt
18715        let tx = create_mock_realloc_tx(
18716            &mint_keypair,
18717            &funding_keypair,
18718            &rent_paying_pubkey,
18719            account_data_size_large,
18720            rent_exempt_minimum_large,
18721            mock_program_id,
18722            recent_blockhash,
18723        );
18724        let result = bank.process_transaction(&tx);
18725        assert!(result.is_ok());
18726        assert_eq!(
18727            rent_exempt_minimum_large,
18728            bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18729        );
18730
18731        // rent exempt, realloc small, fail because not rent exempt
18732        let tx = create_mock_realloc_tx(
18733            &mint_keypair,
18734            &funding_keypair,
18735            &rent_paying_pubkey,
18736            account_data_size_small,
18737            rent_exempt_minimum_small - 1,
18738            mock_program_id,
18739            recent_blockhash,
18740        );
18741        let expected_err = {
18742            let account_index = tx
18743                .message
18744                .account_keys
18745                .iter()
18746                .position(|key| key == &rent_paying_pubkey)
18747                .unwrap() as u8;
18748            TransactionError::InsufficientFundsForRent { account_index }
18749        };
18750        assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18751        assert_eq!(
18752            rent_exempt_minimum_large,
18753            bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18754        );
18755
18756        // rent exempt, realloc smaller and rent exempt
18757        let tx = create_mock_realloc_tx(
18758            &mint_keypair,
18759            &funding_keypair,
18760            &rent_paying_pubkey,
18761            account_data_size_small,
18762            rent_exempt_minimum_small,
18763            mock_program_id,
18764            recent_blockhash,
18765        );
18766        let result = bank.process_transaction(&tx);
18767        assert!(result.is_ok());
18768        assert_eq!(
18769            rent_exempt_minimum_small,
18770            bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18771        );
18772
18773        // rent exempt, realloc large, fail because not rent exempt
18774        let tx = create_mock_realloc_tx(
18775            &mint_keypair,
18776            &funding_keypair,
18777            &rent_paying_pubkey,
18778            account_data_size_large,
18779            rent_exempt_minimum_large - 1,
18780            mock_program_id,
18781            recent_blockhash,
18782        );
18783        let expected_err = {
18784            let account_index = tx
18785                .message
18786                .account_keys
18787                .iter()
18788                .position(|key| key == &rent_paying_pubkey)
18789                .unwrap() as u8;
18790            TransactionError::InsufficientFundsForRent { account_index }
18791        };
18792        assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18793        assert_eq!(
18794            rent_exempt_minimum_small,
18795            bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18796        );
18797
18798        // rent exempt, realloc large and rent exempt
18799        let tx = create_mock_realloc_tx(
18800            &mint_keypair,
18801            &funding_keypair,
18802            &rent_paying_pubkey,
18803            account_data_size_large,
18804            rent_exempt_minimum_large,
18805            mock_program_id,
18806            recent_blockhash,
18807        );
18808        let result = bank.process_transaction(&tx);
18809        assert!(result.is_ok());
18810        assert_eq!(
18811            rent_exempt_minimum_large,
18812            bank.get_account(&rent_paying_pubkey).unwrap().lamports()
18813        );
18814
18815        let created_keypair = Keypair::new();
18816
18817        // create account, not rent exempt
18818        let tx = system_transaction::create_account(
18819            &mint_keypair,
18820            &created_keypair,
18821            recent_blockhash,
18822            rent_exempt_minimum_small - 1,
18823            account_data_size_small as u64,
18824            &system_program::id(),
18825        );
18826        let expected_err = {
18827            let account_index = tx
18828                .message
18829                .account_keys
18830                .iter()
18831                .position(|key| key == &created_keypair.pubkey())
18832                .unwrap() as u8;
18833            TransactionError::InsufficientFundsForRent { account_index }
18834        };
18835        assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18836
18837        // create account, rent exempt
18838        let tx = system_transaction::create_account(
18839            &mint_keypair,
18840            &created_keypair,
18841            recent_blockhash,
18842            rent_exempt_minimum_small,
18843            account_data_size_small as u64,
18844            &system_program::id(),
18845        );
18846        let result = bank.process_transaction(&tx);
18847        assert!(result.is_ok());
18848        assert_eq!(
18849            rent_exempt_minimum_small,
18850            bank.get_account(&created_keypair.pubkey())
18851                .unwrap()
18852                .lamports()
18853        );
18854
18855        let created_keypair = Keypair::new();
18856        // create account, no data
18857        let tx = system_transaction::create_account(
18858            &mint_keypair,
18859            &created_keypair,
18860            recent_blockhash,
18861            rent_exempt_minimum_small - 1,
18862            0,
18863            &system_program::id(),
18864        );
18865        let result = bank.process_transaction(&tx);
18866        assert!(result.is_ok());
18867        assert_eq!(
18868            rent_exempt_minimum_small - 1,
18869            bank.get_account(&created_keypair.pubkey())
18870                .unwrap()
18871                .lamports()
18872        );
18873
18874        // alloc but not rent exempt
18875        let tx = system_transaction::allocate(
18876            &mint_keypair,
18877            &created_keypair,
18878            recent_blockhash,
18879            (account_data_size_small + 1) as u64,
18880        );
18881        let expected_err = {
18882            let account_index = tx
18883                .message
18884                .account_keys
18885                .iter()
18886                .position(|key| key == &created_keypair.pubkey())
18887                .unwrap() as u8;
18888            TransactionError::InsufficientFundsForRent { account_index }
18889        };
18890        assert_eq!(bank.process_transaction(&tx).unwrap_err(), expected_err);
18891
18892        // bring balance of account up to rent exemption
18893        let tx = system_transaction::transfer(
18894            &mint_keypair,
18895            &created_keypair.pubkey(),
18896            1,
18897            recent_blockhash,
18898        );
18899        let result = bank.process_transaction(&tx);
18900        assert!(result.is_ok());
18901        assert_eq!(
18902            rent_exempt_minimum_small,
18903            bank.get_account(&created_keypair.pubkey())
18904                .unwrap()
18905                .lamports()
18906        );
18907
18908        // allocate as rent exempt
18909        let tx = system_transaction::allocate(
18910            &mint_keypair,
18911            &created_keypair,
18912            recent_blockhash,
18913            account_data_size_small as u64,
18914        );
18915        let result = bank.process_transaction(&tx);
18916        assert!(result.is_ok());
18917        assert_eq!(
18918            rent_exempt_minimum_small,
18919            bank.get_account(&created_keypair.pubkey())
18920                .unwrap()
18921                .lamports()
18922        );
18923    }
18924
18925    /// Ensure that accounts data size is updated correctly on resize transactions
18926    #[test]
18927    fn test_accounts_data_size_and_resize_transactions() {
18928        let GenesisConfigInfo {
18929            genesis_config,
18930            mint_keypair,
18931            ..
18932        } = genesis_utils::create_genesis_config(100 * LAMPORTS_PER_SAFE);
18933        let mut bank = Bank::new_for_tests(&genesis_config);
18934        let mock_program_id = Pubkey::new_unique();
18935        bank.add_builtin(
18936            "mock_realloc_program",
18937            &mock_program_id,
18938            mock_realloc_process_instruction,
18939        );
18940        let recent_blockhash = bank.last_blockhash();
18941
18942        let funding_keypair = Keypair::new();
18943        bank.store_account(
18944            &funding_keypair.pubkey(),
18945            &AccountSharedData::new(10 * LAMPORTS_PER_SAFE, 0, &mock_program_id),
18946        );
18947
18948        let mut rng = rand::thread_rng();
18949
18950        // Test case: Grow account
18951        {
18952            let account_pubkey = Pubkey::new_unique();
18953            let account_balance = LAMPORTS_PER_SAFE;
18954            let account_size = rng.gen_range(1, MAX_PERMITTED_DATA_LENGTH) as usize;
18955            let account_data =
18956                AccountSharedData::new(account_balance, account_size, &mock_program_id);
18957            bank.store_account(&account_pubkey, &account_data);
18958
18959            let accounts_data_size_before = bank.load_accounts_data_size();
18960            let account_grow_size = rng.gen_range(1, MAX_PERMITTED_DATA_INCREASE);
18961            let transaction = create_mock_realloc_tx(
18962                &mint_keypair,
18963                &funding_keypair,
18964                &account_pubkey,
18965                account_size + account_grow_size,
18966                account_balance,
18967                mock_program_id,
18968                recent_blockhash,
18969            );
18970            let result = bank.process_transaction(&transaction);
18971            assert!(result.is_ok());
18972            let accounts_data_size_after = bank.load_accounts_data_size();
18973            assert_eq!(
18974                accounts_data_size_after,
18975                accounts_data_size_before.saturating_add(account_grow_size as u64),
18976            );
18977        }
18978
18979        // Test case: Shrink account
18980        {
18981            let account_pubkey = Pubkey::new_unique();
18982            let account_balance = LAMPORTS_PER_SAFE;
18983            let account_size =
18984                rng.gen_range(MAX_PERMITTED_DATA_LENGTH / 2, MAX_PERMITTED_DATA_LENGTH) as usize;
18985            let account_data =
18986                AccountSharedData::new(account_balance, account_size, &mock_program_id);
18987            bank.store_account(&account_pubkey, &account_data);
18988
18989            let accounts_data_size_before = bank.load_accounts_data_size();
18990            let account_shrink_size = rng.gen_range(1, account_size);
18991            let transaction = create_mock_realloc_tx(
18992                &mint_keypair,
18993                &funding_keypair,
18994                &account_pubkey,
18995                account_size - account_shrink_size,
18996                account_balance,
18997                mock_program_id,
18998                recent_blockhash,
18999            );
19000            let result = bank.process_transaction(&transaction);
19001            assert!(result.is_ok());
19002            let accounts_data_size_after = bank.load_accounts_data_size();
19003            assert_eq!(
19004                accounts_data_size_after,
19005                accounts_data_size_before.saturating_sub(account_shrink_size as u64),
19006            );
19007        }
19008    }
19009
19010    #[test]
19011    fn test_get_partition_end_indexes() {
19012        for n in 5..7 {
19013            assert_eq!(vec![0], Bank::get_partition_end_indexes(&(0, 0, n)));
19014            assert!(Bank::get_partition_end_indexes(&(1, 1, n)).is_empty());
19015            assert_eq!(vec![1], Bank::get_partition_end_indexes(&(0, 1, n)));
19016            assert_eq!(vec![1, 2], Bank::get_partition_end_indexes(&(0, 2, n)));
19017            assert_eq!(vec![3, 4], Bank::get_partition_end_indexes(&(2, 4, n)));
19018        }
19019    }
19020
19021    #[test]
19022    fn test_get_rent_paying_pubkeys() {
19023        let lamports = 1;
19024        let bank = create_simple_test_bank(lamports);
19025
19026        let n = 432_000;
19027        assert!(bank.get_rent_paying_pubkeys(&(0, 1, n)).is_none());
19028        assert!(bank.get_rent_paying_pubkeys(&(0, 2, n)).is_none());
19029        assert!(bank.get_rent_paying_pubkeys(&(0, 0, n)).is_none());
19030
19031        let pk1 = Pubkey::from([2; 32]);
19032        let pk2 = Pubkey::from([3; 32]);
19033        let index1 = Bank::partition_from_pubkey(&pk1, n);
19034        let index2 = Bank::partition_from_pubkey(&pk2, n);
19035        assert!(index1 > 0, "{}", index1);
19036        assert!(index2 > index1, "{}, {}", index2, index1);
19037
19038        let epoch_schedule = EpochSchedule::custom(n, 0, false);
19039
19040        let mut rent_paying_accounts_by_partition =
19041            RentPayingAccountsByPartition::new(&epoch_schedule);
19042        rent_paying_accounts_by_partition.add_account(&pk1);
19043        rent_paying_accounts_by_partition.add_account(&pk2);
19044
19045        bank.rc
19046            .accounts
19047            .accounts_db
19048            .accounts_index
19049            .rent_paying_accounts_by_partition
19050            .set(rent_paying_accounts_by_partition)
19051            .unwrap();
19052
19053        assert_eq!(
19054            bank.get_rent_paying_pubkeys(&(0, 1, n)),
19055            Some(HashSet::default())
19056        );
19057        assert_eq!(
19058            bank.get_rent_paying_pubkeys(&(0, 2, n)),
19059            Some(HashSet::default())
19060        );
19061        assert_eq!(
19062            bank.get_rent_paying_pubkeys(&(index1.saturating_sub(1), index1, n)),
19063            Some(HashSet::from([pk1]))
19064        );
19065        assert_eq!(
19066            bank.get_rent_paying_pubkeys(&(index2.saturating_sub(1), index2, n)),
19067            Some(HashSet::from([pk2]))
19068        );
19069        assert_eq!(
19070            bank.get_rent_paying_pubkeys(&(index1.saturating_sub(1), index2, n)),
19071            Some(HashSet::from([pk2, pk1]))
19072        );
19073        assert_eq!(
19074            bank.get_rent_paying_pubkeys(&(0, 0, n)),
19075            Some(HashSet::default())
19076        );
19077    }
19078
19079    /// Ensure that accounts data size is updated correctly by rent collection
19080    #[test]
19081    fn test_accounts_data_size_and_rent_collection() {
19082        let GenesisConfigInfo {
19083            mut genesis_config, ..
19084        } = genesis_utils::create_genesis_config(100 * LAMPORTS_PER_SAFE);
19085        genesis_config.rent = Rent::default();
19086        activate_all_features(&mut genesis_config);
19087        let bank = Arc::new(Bank::new_for_tests(&genesis_config));
19088        let bank = Arc::new(Bank::new_from_parent(
19089            &bank,
19090            &Pubkey::default(),
19091            bank.slot() + bank.slot_count_per_normal_epoch(),
19092        ));
19093
19094        // make another bank so that any reclaimed accounts from the previous bank do not impact
19095        // this test
19096        let bank = Arc::new(Bank::new_from_parent(
19097            &bank,
19098            &Pubkey::default(),
19099            bank.slot() + bank.slot_count_per_normal_epoch(),
19100        ));
19101
19102        // Store an account into the bank that is rent-paying and has data
19103        let data_size = 123;
19104        let mut account = AccountSharedData::new(1, data_size, &Pubkey::default());
19105        let keypair = Keypair::new();
19106        bank.store_account(&keypair.pubkey(), &account);
19107
19108        // Ensure if we collect rent from the account that it will be reclaimed
19109        {
19110            let info = bank.rent_collector.collect_from_existing_account(
19111                &keypair.pubkey(),
19112                &mut account,
19113                None,
19114                true, // preserve_rent_epoch_for_rent_exempt_accounts
19115            );
19116            assert_eq!(info.account_data_len_reclaimed, data_size as u64);
19117        }
19118
19119        // Collect rent for real
19120        let accounts_data_size_delta_before_collecting_rent = bank.load_accounts_data_size_delta();
19121        bank.collect_rent_eagerly(false);
19122        let accounts_data_size_delta_after_collecting_rent = bank.load_accounts_data_size_delta();
19123
19124        let accounts_data_size_delta_delta = accounts_data_size_delta_after_collecting_rent as i64
19125            - accounts_data_size_delta_before_collecting_rent as i64;
19126        assert!(accounts_data_size_delta_delta < 0);
19127        let reclaimed_data_size = accounts_data_size_delta_delta.saturating_neg() as usize;
19128
19129        // Ensure the account is reclaimed by rent collection
19130        assert_eq!(reclaimed_data_size, data_size,);
19131    }
19132
19133    #[test]
19134    fn test_accounts_data_size_with_default_bank() {
19135        let bank = Bank::default_for_tests();
19136        assert_eq!(
19137            bank.load_accounts_data_size() as usize,
19138            bank.get_total_accounts_stats().unwrap().data_len
19139        );
19140    }
19141
19142    #[test]
19143    fn test_accounts_data_size_from_genesis() {
19144        let GenesisConfigInfo {
19145            mut genesis_config,
19146            mint_keypair,
19147            ..
19148        } = genesis_utils::create_genesis_config_with_leader(
19149            1_000_000 * LAMPORTS_PER_SAFE,
19150            &Pubkey::new_unique(),
19151            100 * LAMPORTS_PER_SAFE,
19152        );
19153        genesis_config.rent = Rent::default();
19154        genesis_config.ticks_per_slot = 3;
19155
19156        let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
19157        assert_eq!(
19158            bank.load_accounts_data_size() as usize,
19159            bank.get_total_accounts_stats().unwrap().data_len
19160        );
19161
19162        // Create accounts over a number of banks and ensure the accounts data size remains correct
19163        for _ in 0..10 {
19164            bank = Arc::new(Bank::new_from_parent(
19165                &bank,
19166                &Pubkey::default(),
19167                bank.slot() + 1,
19168            ));
19169
19170            // Store an account into the bank that is rent-exempt and has data
19171            let data_size = rand::thread_rng().gen_range(3333, 4444);
19172            let transaction = system_transaction::create_account(
19173                &mint_keypair,
19174                &Keypair::new(),
19175                bank.last_blockhash(),
19176                genesis_config.rent.minimum_balance(data_size),
19177                data_size as u64,
19178                &solana_sdk::system_program::id(),
19179            );
19180            bank.process_transaction(&transaction).unwrap();
19181            bank.fill_bank_with_ticks_for_tests();
19182
19183            assert_eq!(
19184                bank.load_accounts_data_size() as usize,
19185                bank.get_total_accounts_stats().unwrap().data_len,
19186            );
19187        }
19188    }
19189
19190    #[test]
19191    fn test_calculate_fee_with_request_heap_frame_flag() {
19192        let key0 = Pubkey::new_unique();
19193        let key1 = Pubkey::new_unique();
19194        let lamports_per_signature: u64 = 5_000;
19195        let signature_fee: u64 = 10;
19196        let request_cu: u64 = 1;
19197        let lamports_per_cu: u64 = 5;
19198        let fee_structure = FeeStructure {
19199            lamports_per_signature: signature_fee,
19200            ..FeeStructure::default()
19201        };
19202        let message = SanitizedMessage::try_from(Message::new(
19203            &[
19204                system_instruction::transfer(&key0, &key1, 1),
19205                ComputeBudgetInstruction::set_compute_unit_limit(request_cu as u32),
19206                ComputeBudgetInstruction::request_heap_frame(40 * 1024),
19207                ComputeBudgetInstruction::set_compute_unit_price(lamports_per_cu * 1_000_000),
19208            ],
19209            Some(&key0),
19210        ))
19211        .unwrap();
19212
19213        // assert when enable_request_heap_frame_ix is enabled, prioritization fee will be counted
19214        // into transaction fee
19215        let mut enable_request_heap_frame_ix = true;
19216        assert_eq!(
19217            Bank::calculate_fee(
19218                &message,
19219                lamports_per_signature,
19220                &fee_structure,
19221                true,
19222                true,
19223                enable_request_heap_frame_ix,
19224            ),
19225            signature_fee + request_cu * lamports_per_cu
19226        );
19227
19228        // assert when enable_request_heap_frame_ix is disabled (an v1.13 behavior), prioritization fee will not be counted
19229        // into transaction fee
19230        enable_request_heap_frame_ix = false;
19231        assert_eq!(
19232            Bank::calculate_fee(
19233                &message,
19234                lamports_per_signature,
19235                &fee_structure,
19236                true,
19237                true,
19238                enable_request_heap_frame_ix,
19239            ),
19240            signature_fee
19241        );
19242    }
19243}