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.
36use {
37    crate::{
38        account_saver::collect_accounts_to_store,
39        bank::{
40            metrics::*,
41            partitioned_epoch_rewards::{EpochRewardStatus, StakeRewards, VoteRewardsAccounts},
42        },
43        bank_forks::BankForks,
44        epoch_stakes::{split_epoch_stakes, EpochStakes, NodeVoteAccounts, VersionedEpochStakes},
45        installed_scheduler_pool::{BankWithScheduler, InstalledSchedulerRwLock},
46        rent_collector::RentCollectorWithMetrics,
47        runtime_config::RuntimeConfig,
48        serde_snapshot::BankIncrementalSnapshotPersistence,
49        snapshot_hash::SnapshotHash,
50        stake_account::StakeAccount,
51        stake_weighted_timestamp::{
52            calculate_stake_weighted_timestamp, MaxAllowableDrift,
53            MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST, MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
54        },
55        stakes::{Stakes, StakesCache, StakesEnum},
56        status_cache::{SlotDelta, StatusCache},
57        transaction_batch::{OwnedOrBorrowed, TransactionBatch},
58        verify_precompiles::verify_precompiles,
59    },
60    accounts_lt_hash::{CacheValue as AccountsLtHashCacheValue, Stats as AccountsLtHashStats},
61    ahash::AHashSet,
62    dashmap::{DashMap, DashSet},
63    log::*,
64    rayon::{
65        iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator},
66        ThreadPoolBuilder,
67    },
68    serde::Serialize,
69    solana_accounts_db::{
70        account_locks::validate_account_locks,
71        accounts::{AccountAddressFilter, Accounts, PubkeyAccountSlot},
72        accounts_db::{
73            AccountStorageEntry, AccountsDb, AccountsDbConfig, CalcAccountsHashDataSource,
74            DuplicatesLtHash, OldStoragesPolicy, PubkeyHashAccount,
75            VerifyAccountsHashAndLamportsConfig,
76        },
77        accounts_hash::{
78            AccountHash, AccountsHash, AccountsLtHash, CalcAccountsHashConfig, HashStats,
79            IncrementalAccountsHash, MerkleOrLatticeAccountsHash,
80        },
81        accounts_index::{IndexKey, ScanConfig, ScanResult},
82        accounts_partition::{self, Partition, PartitionIndex},
83        accounts_update_notifier_interface::AccountsUpdateNotifier,
84        ancestors::{Ancestors, AncestorsForSerialization},
85        blockhash_queue::BlockhashQueue,
86        epoch_accounts_hash::EpochAccountsHash,
87        sorted_storages::SortedStorages,
88        storable_accounts::StorableAccounts,
89    },
90    solana_bpf_loader_program::syscalls::{
91        create_program_runtime_environment_v1, create_program_runtime_environment_v2,
92    },
93    solana_builtins::{prototype::BuiltinPrototype, BUILTINS, STATELESS_BUILTINS},
94    solana_compute_budget::compute_budget::ComputeBudget,
95    solana_compute_budget_instruction::instructions_processor::process_compute_budget_instructions,
96    solana_cost_model::{block_cost_limits::simd_0207_block_limits, cost_tracker::CostTracker},
97    solana_feature_set::{self as feature_set, reward_full_priority_fee, FeatureSet},
98    solana_fee::FeeFeatures,
99    solana_lattice_hash::lt_hash::LtHash,
100    solana_measure::{meas_dur, measure::Measure, measure_time, measure_us},
101    solana_program_runtime::{
102        invoke_context::BuiltinFunctionWithContext, loaded_programs::ProgramCacheEntry,
103    },
104    solana_runtime_transaction::{
105        runtime_transaction::RuntimeTransaction, transaction_with_meta::TransactionWithMeta,
106    },
107    solana_sdk::{
108        account::{
109            create_account_shared_data_with_fields as create_account, from_account, Account,
110            AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
111        },
112        bpf_loader_upgradeable,
113        clock::{
114            BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_HASHES_PER_TICK,
115            DEFAULT_TICKS_PER_SECOND, INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE,
116            MAX_TRANSACTION_FORWARDING_DELAY, SECONDS_PER_DAY, UPDATED_HASHES_PER_TICK2,
117            UPDATED_HASHES_PER_TICK3, UPDATED_HASHES_PER_TICK4, UPDATED_HASHES_PER_TICK5,
118            UPDATED_HASHES_PER_TICK6,
119        },
120        epoch_info::EpochInfo,
121        epoch_schedule::EpochSchedule,
122        feature,
123        fee::{FeeBudgetLimits, FeeDetails, FeeStructure},
124        fee_calculator::FeeRateGovernor,
125        genesis_config::{ClusterType, GenesisConfig},
126        hard_forks::HardForks,
127        hash::{extend_and_hash, hashv, Hash},
128        incinerator,
129        inflation::Inflation,
130        inner_instruction::InnerInstructions,
131        message::{AccountKeys, SanitizedMessage},
132        native_loader,
133        native_token::LAMPORTS_PER_SOL,
134        packet::PACKET_DATA_SIZE,
135        precompiles::get_precompiles,
136        pubkey::Pubkey,
137        rent_collector::{CollectedInfo, RentCollector},
138        rent_debits::RentDebits,
139        reserved_account_keys::ReservedAccountKeys,
140        reward_info::RewardInfo,
141        signature::{Keypair, Signature},
142        slot_hashes::SlotHashes,
143        slot_history::{Check, SlotHistory},
144        stake::state::Delegation,
145        system_transaction,
146        sysvar::{self, last_restart_slot::LastRestartSlot, Sysvar, SysvarId},
147        timing::years_as_slots,
148        transaction::{
149            MessageHash, Result, SanitizedTransaction, Transaction, TransactionError,
150            TransactionVerificationMode, VersionedTransaction, MAX_TX_ACCOUNT_LOCKS,
151        },
152        transaction_context::{TransactionAccount, TransactionReturnData},
153    },
154    solana_stake_program::points::InflationPointCalculationEvent,
155    solana_svm::{
156        account_loader::{collect_rent_from_account, LoadedTransaction},
157        account_overrides::AccountOverrides,
158        transaction_commit_result::{CommittedTransaction, TransactionCommitResult},
159        transaction_error_metrics::TransactionErrorMetrics,
160        transaction_execution_result::{
161            TransactionExecutionDetails, TransactionLoadedAccountsStats,
162        },
163        transaction_processing_callback::{AccountState, TransactionProcessingCallback},
164        transaction_processing_result::{
165            ProcessedTransaction, TransactionProcessingResult,
166            TransactionProcessingResultExtensions,
167        },
168        transaction_processor::{
169            ExecutionRecordingConfig, TransactionBatchProcessor, TransactionLogMessages,
170            TransactionProcessingConfig, TransactionProcessingEnvironment,
171        },
172    },
173    solana_svm_transaction::svm_message::SVMMessage,
174    solana_timings::{ExecuteTimingType, ExecuteTimings},
175    solana_vote::vote_account::{VoteAccount, VoteAccountsHashMap},
176    std::{
177        collections::{HashMap, HashSet},
178        convert::TryFrom,
179        fmt,
180        ops::{AddAssign, RangeFull, RangeInclusive},
181        path::PathBuf,
182        slice,
183        sync::{
184            atomic::{
185                AtomicBool, AtomicI64, AtomicU64, AtomicUsize,
186                Ordering::{AcqRel, Acquire, Relaxed},
187            },
188            Arc, LockResult, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard, Weak,
189        },
190        thread::Builder,
191        time::{Duration, Instant},
192    },
193};
194pub use {
195    partitioned_epoch_rewards::KeyedRewardsAndNumPartitions, solana_sdk::reward_type::RewardType,
196};
197#[cfg(feature = "dev-context-only-utils")]
198use {
199    solana_accounts_db::accounts_db::{
200        ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING,
201    },
202    solana_nonce_account::{get_system_account_kind, SystemAccountKind},
203    solana_program_runtime::{loaded_programs::ProgramCacheForTxBatch, sysvar_cache::SysvarCache},
204    solana_sdk::nonce,
205    solana_svm::program_loader::load_program_with_pubkey,
206};
207
208/// params to `verify_accounts_hash`
209struct VerifyAccountsHashConfig {
210    test_hash_calculation: bool,
211    ignore_mismatch: bool,
212    require_rooted_bank: bool,
213    run_in_background: bool,
214    store_hash_raw_data_for_debug: bool,
215}
216
217mod accounts_lt_hash;
218mod address_lookup_table;
219pub mod bank_hash_details;
220mod builtin_programs;
221pub mod builtins;
222mod check_transactions;
223pub mod epoch_accounts_hash_utils;
224mod fee_distribution;
225mod metrics;
226pub(crate) mod partitioned_epoch_rewards;
227mod recent_blockhashes_account;
228mod serde_snapshot;
229mod sysvar_cache;
230pub(crate) mod tests;
231
232pub const SECONDS_PER_YEAR: f64 = 365.25 * 24.0 * 60.0 * 60.0;
233
234pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5;
235
236#[derive(Default)]
237struct RentMetrics {
238    hold_range_us: AtomicU64,
239    load_us: AtomicU64,
240    collect_us: AtomicU64,
241    hash_us: AtomicU64,
242    store_us: AtomicU64,
243    count: AtomicUsize,
244}
245
246pub type BankStatusCache = StatusCache<Result<()>>;
247#[cfg_attr(
248    feature = "frozen-abi",
249    frozen_abi(digest = "4e7a7AAsQrM5Lp5bhREdVZ5QGZfyETbBthhWjYMYb6zS")
250)]
251pub type BankSlotDelta = SlotDelta<Result<()>>;
252
253#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
254pub struct SquashTiming {
255    pub squash_accounts_ms: u64,
256    pub squash_accounts_cache_ms: u64,
257    pub squash_accounts_index_ms: u64,
258    pub squash_accounts_store_ms: u64,
259
260    pub squash_cache_ms: u64,
261}
262
263impl AddAssign for SquashTiming {
264    fn add_assign(&mut self, rhs: Self) {
265        self.squash_accounts_ms += rhs.squash_accounts_ms;
266        self.squash_accounts_cache_ms += rhs.squash_accounts_cache_ms;
267        self.squash_accounts_index_ms += rhs.squash_accounts_index_ms;
268        self.squash_accounts_store_ms += rhs.squash_accounts_store_ms;
269        self.squash_cache_ms += rhs.squash_cache_ms;
270    }
271}
272
273#[derive(Debug, Default, PartialEq)]
274pub(crate) struct CollectorFeeDetails {
275    transaction_fee: u64,
276    priority_fee: u64,
277}
278
279impl CollectorFeeDetails {
280    pub(crate) fn accumulate(&mut self, fee_details: &FeeDetails) {
281        self.transaction_fee = self
282            .transaction_fee
283            .saturating_add(fee_details.transaction_fee());
284        self.priority_fee = self
285            .priority_fee
286            .saturating_add(fee_details.prioritization_fee());
287    }
288
289    pub(crate) fn total(&self) -> u64 {
290        self.transaction_fee.saturating_add(self.priority_fee)
291    }
292}
293
294impl From<FeeDetails> for CollectorFeeDetails {
295    fn from(fee_details: FeeDetails) -> Self {
296        CollectorFeeDetails {
297            transaction_fee: fee_details.transaction_fee(),
298            priority_fee: fee_details.prioritization_fee(),
299        }
300    }
301}
302
303#[derive(Debug)]
304pub struct BankRc {
305    /// where all the Accounts are stored
306    pub accounts: Arc<Accounts>,
307
308    /// Previous checkpoint of this bank
309    pub(crate) parent: RwLock<Option<Arc<Bank>>>,
310
311    pub(crate) bank_id_generator: Arc<AtomicU64>,
312}
313
314impl BankRc {
315    pub(crate) fn new(accounts: Accounts) -> Self {
316        Self {
317            accounts: Arc::new(accounts),
318            parent: RwLock::new(None),
319            bank_id_generator: Arc::new(AtomicU64::new(0)),
320        }
321    }
322}
323
324pub struct LoadAndExecuteTransactionsOutput {
325    // Vector of results indicating whether a transaction was processed or could not
326    // be processed. Note processed transactions can still have failed!
327    pub processing_results: Vec<TransactionProcessingResult>,
328    // Processed transaction counts used to update bank transaction counts and
329    // for metrics reporting.
330    pub processed_counts: ProcessedTransactionCounts,
331}
332
333#[derive(Debug, PartialEq)]
334pub struct TransactionSimulationResult {
335    pub result: Result<()>,
336    pub logs: TransactionLogMessages,
337    pub post_simulation_accounts: Vec<TransactionAccount>,
338    pub units_consumed: u64,
339    pub return_data: Option<TransactionReturnData>,
340    pub inner_instructions: Option<Vec<InnerInstructions>>,
341}
342
343#[derive(Clone, Debug)]
344pub struct TransactionBalancesSet {
345    pub pre_balances: TransactionBalances,
346    pub post_balances: TransactionBalances,
347}
348
349impl TransactionBalancesSet {
350    pub fn new(pre_balances: TransactionBalances, post_balances: TransactionBalances) -> Self {
351        assert_eq!(pre_balances.len(), post_balances.len());
352        Self {
353            pre_balances,
354            post_balances,
355        }
356    }
357}
358pub type TransactionBalances = Vec<Vec<u64>>;
359
360pub type PreCommitResult<'a> = Result<Option<RwLockReadGuard<'a, Hash>>>;
361
362#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
363pub enum TransactionLogCollectorFilter {
364    All,
365    AllWithVotes,
366    None,
367    OnlyMentionedAddresses,
368}
369
370impl Default for TransactionLogCollectorFilter {
371    fn default() -> Self {
372        Self::None
373    }
374}
375
376#[derive(Debug, Default)]
377pub struct TransactionLogCollectorConfig {
378    pub mentioned_addresses: HashSet<Pubkey>,
379    pub filter: TransactionLogCollectorFilter,
380}
381
382#[derive(Clone, Debug, PartialEq, Eq)]
383pub struct TransactionLogInfo {
384    pub signature: Signature,
385    pub result: Result<()>,
386    pub is_vote: bool,
387    pub log_messages: TransactionLogMessages,
388}
389
390#[derive(Default, Debug)]
391pub struct TransactionLogCollector {
392    // All the logs collected for from this Bank.  Exact contents depend on the
393    // active `TransactionLogCollectorFilter`
394    pub logs: Vec<TransactionLogInfo>,
395
396    // For each `mentioned_addresses`, maintain a list of indices into `logs` to easily
397    // locate the logs from transactions that included the mentioned addresses.
398    pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>,
399}
400
401impl TransactionLogCollector {
402    pub fn get_logs_for_address(
403        &self,
404        address: Option<&Pubkey>,
405    ) -> Option<Vec<TransactionLogInfo>> {
406        match address {
407            None => Some(self.logs.clone()),
408            Some(address) => self.mentioned_address_map.get(address).map(|log_indices| {
409                log_indices
410                    .iter()
411                    .filter_map(|i| self.logs.get(*i).cloned())
412                    .collect()
413            }),
414        }
415    }
416}
417
418/// Bank's common fields shared by all supported snapshot versions for deserialization.
419/// Sync fields with BankFieldsToSerialize! This is paired with it.
420/// All members are made public to remain Bank's members private and to make versioned deserializer workable on this
421/// Note that some fields are missing from the serializer struct. This is because of fields added later.
422/// Since it is difficult to insert fields to serialize/deserialize against existing code already deployed,
423/// new fields can be optionally serialized and optionally deserialized. At some point, the serialization and
424/// deserialization will use a new mechanism or otherwise be in sync more clearly.
425#[derive(Clone, Debug, Default)]
426#[cfg_attr(feature = "dev-context-only-utils", derive(PartialEq))]
427pub struct BankFieldsToDeserialize {
428    pub(crate) blockhash_queue: BlockhashQueue,
429    pub(crate) ancestors: AncestorsForSerialization,
430    pub(crate) hash: Hash,
431    pub(crate) parent_hash: Hash,
432    pub(crate) parent_slot: Slot,
433    pub(crate) hard_forks: HardForks,
434    pub(crate) transaction_count: u64,
435    pub(crate) tick_height: u64,
436    pub(crate) signature_count: u64,
437    pub(crate) capitalization: u64,
438    pub(crate) max_tick_height: u64,
439    pub(crate) hashes_per_tick: Option<u64>,
440    pub(crate) ticks_per_slot: u64,
441    pub(crate) ns_per_slot: u128,
442    pub(crate) genesis_creation_time: UnixTimestamp,
443    pub(crate) slots_per_year: f64,
444    pub(crate) slot: Slot,
445    pub(crate) epoch: Epoch,
446    pub(crate) block_height: u64,
447    pub(crate) collector_id: Pubkey,
448    pub(crate) collector_fees: u64,
449    pub(crate) fee_rate_governor: FeeRateGovernor,
450    pub(crate) collected_rent: u64,
451    pub(crate) rent_collector: RentCollector,
452    pub(crate) epoch_schedule: EpochSchedule,
453    pub(crate) inflation: Inflation,
454    pub(crate) stakes: Stakes<Delegation>,
455    pub(crate) epoch_stakes: HashMap<Epoch, EpochStakes>,
456    pub(crate) is_delta: bool,
457    pub(crate) accounts_data_len: u64,
458    pub(crate) incremental_snapshot_persistence: Option<BankIncrementalSnapshotPersistence>,
459    pub(crate) epoch_accounts_hash: Option<Hash>,
460    // When removing the accounts lt hash featurization code, also remove this Option wrapper
461    pub(crate) accounts_lt_hash: Option<AccountsLtHash>,
462    pub(crate) bank_hash_stats: BankHashStats,
463}
464
465/// Bank's common fields shared by all supported snapshot versions for serialization.
466/// This was separated from BankFieldsToDeserialize to avoid cloning by using refs.
467/// So, sync fields with BankFieldsToDeserialize!
468/// all members are made public to keep Bank private and to make versioned serializer workable on this.
469/// Note that some fields are missing from the serializer struct. This is because of fields added later.
470/// Since it is difficult to insert fields to serialize/deserialize against existing code already deployed,
471/// new fields can be optionally serialized and optionally deserialized. At some point, the serialization and
472/// deserialization will use a new mechanism or otherwise be in sync more clearly.
473#[derive(Debug)]
474pub struct BankFieldsToSerialize {
475    pub blockhash_queue: BlockhashQueue,
476    pub ancestors: AncestorsForSerialization,
477    pub hash: Hash,
478    pub parent_hash: Hash,
479    pub parent_slot: Slot,
480    pub hard_forks: HardForks,
481    pub transaction_count: u64,
482    pub tick_height: u64,
483    pub signature_count: u64,
484    pub capitalization: u64,
485    pub max_tick_height: u64,
486    pub hashes_per_tick: Option<u64>,
487    pub ticks_per_slot: u64,
488    pub ns_per_slot: u128,
489    pub genesis_creation_time: UnixTimestamp,
490    pub slots_per_year: f64,
491    pub slot: Slot,
492    pub epoch: Epoch,
493    pub block_height: u64,
494    pub collector_id: Pubkey,
495    pub collector_fees: u64,
496    pub fee_rate_governor: FeeRateGovernor,
497    pub collected_rent: u64,
498    pub rent_collector: RentCollector,
499    pub epoch_schedule: EpochSchedule,
500    pub inflation: Inflation,
501    pub stakes: StakesEnum,
502    pub epoch_stakes: HashMap<Epoch, EpochStakes>,
503    pub is_delta: bool,
504    pub accounts_data_len: u64,
505    pub versioned_epoch_stakes: HashMap<u64, VersionedEpochStakes>,
506    // When removing the accounts lt hash featurization code, also remove this Option wrapper
507    pub accounts_lt_hash: Option<AccountsLtHash>,
508}
509
510// Can't derive PartialEq because RwLock doesn't implement PartialEq
511#[cfg(feature = "dev-context-only-utils")]
512impl PartialEq for Bank {
513    fn eq(&self, other: &Self) -> bool {
514        if std::ptr::eq(self, other) {
515            return true;
516        }
517        // Suppress rustfmt until https://github.com/rust-lang/rustfmt/issues/5920 is fixed ...
518        #[rustfmt::skip]
519        let Self {
520            skipped_rewrites: _,
521            rc: _,
522            status_cache: _,
523            blockhash_queue,
524            ancestors,
525            hash,
526            parent_hash,
527            parent_slot,
528            hard_forks,
529            transaction_count,
530            non_vote_transaction_count_since_restart: _,
531            transaction_error_count: _,
532            transaction_entries_count: _,
533            transactions_per_entry_max: _,
534            tick_height,
535            signature_count,
536            capitalization,
537            max_tick_height,
538            hashes_per_tick,
539            ticks_per_slot,
540            ns_per_slot,
541            genesis_creation_time,
542            slots_per_year,
543            slot,
544            bank_id: _,
545            epoch,
546            block_height,
547            collector_id,
548            collector_fees,
549            fee_rate_governor,
550            collected_rent,
551            rent_collector,
552            epoch_schedule,
553            inflation,
554            stakes_cache,
555            epoch_stakes,
556            is_delta,
557            #[cfg(feature = "dev-context-only-utils")]
558            hash_overrides,
559            accounts_lt_hash,
560            // TODO: Confirm if all these fields are intentionally ignored!
561            rewards: _,
562            cluster_type: _,
563            lazy_rent_collection: _,
564            rewards_pool_pubkeys: _,
565            transaction_debug_keys: _,
566            transaction_log_collector_config: _,
567            transaction_log_collector: _,
568            feature_set: _,
569            reserved_account_keys: _,
570            drop_callback: _,
571            freeze_started: _,
572            vote_only_bank: _,
573            cost_tracker: _,
574            accounts_data_size_initial: _,
575            accounts_data_size_delta_on_chain: _,
576            accounts_data_size_delta_off_chain: _,
577            epoch_reward_status: _,
578            transaction_processor: _,
579            check_program_modification_slot: _,
580            collector_fee_details: _,
581            compute_budget: _,
582            transaction_account_lock_limit: _,
583            fee_structure: _,
584            cache_for_accounts_lt_hash: _,
585            stats_for_accounts_lt_hash: _,
586            block_id,
587            bank_hash_stats: _,
588            // Ignore new fields explicitly if they do not impact PartialEq.
589            // Adding ".." will remove compile-time checks that if a new field
590            // is added to the struct, this PartialEq is accordingly updated.
591        } = self;
592        *blockhash_queue.read().unwrap() == *other.blockhash_queue.read().unwrap()
593            && ancestors == &other.ancestors
594            && *hash.read().unwrap() == *other.hash.read().unwrap()
595            && parent_hash == &other.parent_hash
596            && parent_slot == &other.parent_slot
597            && *hard_forks.read().unwrap() == *other.hard_forks.read().unwrap()
598            && transaction_count.load(Relaxed) == other.transaction_count.load(Relaxed)
599            && tick_height.load(Relaxed) == other.tick_height.load(Relaxed)
600            && signature_count.load(Relaxed) == other.signature_count.load(Relaxed)
601            && capitalization.load(Relaxed) == other.capitalization.load(Relaxed)
602            && max_tick_height == &other.max_tick_height
603            && hashes_per_tick == &other.hashes_per_tick
604            && ticks_per_slot == &other.ticks_per_slot
605            && ns_per_slot == &other.ns_per_slot
606            && genesis_creation_time == &other.genesis_creation_time
607            && slots_per_year == &other.slots_per_year
608            && slot == &other.slot
609            && epoch == &other.epoch
610            && block_height == &other.block_height
611            && collector_id == &other.collector_id
612            && collector_fees.load(Relaxed) == other.collector_fees.load(Relaxed)
613            && fee_rate_governor == &other.fee_rate_governor
614            && collected_rent.load(Relaxed) == other.collected_rent.load(Relaxed)
615            && rent_collector == &other.rent_collector
616            && epoch_schedule == &other.epoch_schedule
617            && *inflation.read().unwrap() == *other.inflation.read().unwrap()
618            && *stakes_cache.stakes() == *other.stakes_cache.stakes()
619            && epoch_stakes == &other.epoch_stakes
620            && is_delta.load(Relaxed) == other.is_delta.load(Relaxed)
621            // No deadlock is possbile, when Arc::ptr_eq() returns false, because of being
622            // different Mutexes.
623            && (Arc::ptr_eq(hash_overrides, &other.hash_overrides) ||
624                *hash_overrides.lock().unwrap() == *other.hash_overrides.lock().unwrap())
625            && !(self.is_accounts_lt_hash_enabled() && other.is_accounts_lt_hash_enabled()
626                && *accounts_lt_hash.lock().unwrap() != *other.accounts_lt_hash.lock().unwrap())
627            && *block_id.read().unwrap() == *other.block_id.read().unwrap()
628    }
629}
630
631#[cfg(feature = "dev-context-only-utils")]
632impl BankFieldsToSerialize {
633    /// Create a new BankFieldsToSerialize where basically every field is defaulted.
634    /// Only use for tests; many of the fields are invalid!
635    pub fn default_for_tests() -> Self {
636        Self {
637            blockhash_queue: BlockhashQueue::default(),
638            ancestors: AncestorsForSerialization::default(),
639            hash: Hash::default(),
640            parent_hash: Hash::default(),
641            parent_slot: Slot::default(),
642            hard_forks: HardForks::default(),
643            transaction_count: u64::default(),
644            tick_height: u64::default(),
645            signature_count: u64::default(),
646            capitalization: u64::default(),
647            max_tick_height: u64::default(),
648            hashes_per_tick: Option::default(),
649            ticks_per_slot: u64::default(),
650            ns_per_slot: u128::default(),
651            genesis_creation_time: UnixTimestamp::default(),
652            slots_per_year: f64::default(),
653            slot: Slot::default(),
654            epoch: Epoch::default(),
655            block_height: u64::default(),
656            collector_id: Pubkey::default(),
657            collector_fees: u64::default(),
658            fee_rate_governor: FeeRateGovernor::default(),
659            collected_rent: u64::default(),
660            rent_collector: RentCollector::default(),
661            epoch_schedule: EpochSchedule::default(),
662            inflation: Inflation::default(),
663            stakes: Stakes::<Delegation>::default().into(),
664            epoch_stakes: HashMap::default(),
665            is_delta: bool::default(),
666            accounts_data_len: u64::default(),
667            versioned_epoch_stakes: HashMap::default(),
668            accounts_lt_hash: Some(AccountsLtHash(LtHash([0x7E57; LtHash::NUM_ELEMENTS]))),
669        }
670    }
671}
672
673#[derive(Debug)]
674pub enum RewardCalculationEvent<'a, 'b> {
675    Staking(&'a Pubkey, &'b InflationPointCalculationEvent),
676}
677
678/// type alias is not supported for trait in rust yet. As a workaround, we define the
679/// `RewardCalcTracer` trait explicitly and implement it on any type that implement
680/// `Fn(&RewardCalculationEvent) + Send + Sync`.
681pub trait RewardCalcTracer: Fn(&RewardCalculationEvent) + Send + Sync {}
682
683impl<T: Fn(&RewardCalculationEvent) + Send + Sync> RewardCalcTracer for T {}
684
685fn null_tracer() -> Option<impl RewardCalcTracer> {
686    None::<fn(&RewardCalculationEvent)>
687}
688
689pub trait DropCallback: fmt::Debug {
690    fn callback(&self, b: &Bank);
691    fn clone_box(&self) -> Box<dyn DropCallback + Send + Sync>;
692}
693
694#[derive(Debug, Default)]
695pub struct OptionalDropCallback(Option<Box<dyn DropCallback + Send + Sync>>);
696
697#[derive(Default, Debug, Clone, PartialEq)]
698#[cfg(feature = "dev-context-only-utils")]
699pub struct HashOverrides {
700    hashes: HashMap<Slot, HashOverride>,
701}
702
703#[cfg(feature = "dev-context-only-utils")]
704impl HashOverrides {
705    fn get_hash_override(&self, slot: Slot) -> Option<&HashOverride> {
706        self.hashes.get(&slot)
707    }
708
709    fn get_blockhash_override(&self, slot: Slot) -> Option<&Hash> {
710        self.get_hash_override(slot)
711            .map(|hash_override| &hash_override.blockhash)
712    }
713
714    fn get_bank_hash_override(&self, slot: Slot) -> Option<&Hash> {
715        self.get_hash_override(slot)
716            .map(|hash_override| &hash_override.bank_hash)
717    }
718
719    pub fn add_override(&mut self, slot: Slot, blockhash: Hash, bank_hash: Hash) {
720        let is_new = self
721            .hashes
722            .insert(
723                slot,
724                HashOverride {
725                    blockhash,
726                    bank_hash,
727                },
728            )
729            .is_none();
730        assert!(is_new);
731    }
732}
733
734#[derive(Debug, Clone, PartialEq)]
735#[cfg(feature = "dev-context-only-utils")]
736struct HashOverride {
737    blockhash: Hash,
738    bank_hash: Hash,
739}
740
741/// Manager for the state of all accounts and programs after processing its entries.
742#[derive(Debug)]
743pub struct Bank {
744    /// References to accounts, parent and signature status
745    pub rc: BankRc,
746
747    /// A cache of signature statuses
748    pub status_cache: Arc<RwLock<BankStatusCache>>,
749
750    /// FIFO queue of `recent_blockhash` items
751    blockhash_queue: RwLock<BlockhashQueue>,
752
753    /// The set of parents including this bank
754    pub ancestors: Ancestors,
755
756    /// Hash of this Bank's state. Only meaningful after freezing.
757    hash: RwLock<Hash>,
758
759    /// Hash of this Bank's parent's state
760    parent_hash: Hash,
761
762    /// parent's slot
763    parent_slot: Slot,
764
765    /// slots to hard fork at
766    hard_forks: Arc<RwLock<HardForks>>,
767
768    /// The number of committed transactions since genesis.
769    transaction_count: AtomicU64,
770
771    /// The number of non-vote transactions committed since the most
772    /// recent boot from snapshot or genesis. This value is only stored in
773    /// blockstore for the RPC method "getPerformanceSamples". It is not
774    /// retained within snapshots, but is preserved in `Bank::new_from_parent`.
775    non_vote_transaction_count_since_restart: AtomicU64,
776
777    /// The number of transaction errors in this slot
778    transaction_error_count: AtomicU64,
779
780    /// The number of transaction entries in this slot
781    transaction_entries_count: AtomicU64,
782
783    /// The max number of transaction in an entry in this slot
784    transactions_per_entry_max: AtomicU64,
785
786    /// Bank tick height
787    tick_height: AtomicU64,
788
789    /// The number of signatures from valid transactions in this slot
790    signature_count: AtomicU64,
791
792    /// Total capitalization, used to calculate inflation
793    capitalization: AtomicU64,
794
795    // Bank max_tick_height
796    max_tick_height: u64,
797
798    /// The number of hashes in each tick. None value means hashing is disabled.
799    hashes_per_tick: Option<u64>,
800
801    /// The number of ticks in each slot.
802    ticks_per_slot: u64,
803
804    /// length of a slot in ns
805    pub ns_per_slot: u128,
806
807    /// genesis time, used for computed clock
808    genesis_creation_time: UnixTimestamp,
809
810    /// The number of slots per year, used for inflation
811    slots_per_year: f64,
812
813    /// Bank slot (i.e. block)
814    slot: Slot,
815
816    bank_id: BankId,
817
818    /// Bank epoch
819    epoch: Epoch,
820
821    /// Bank block_height
822    block_height: u64,
823
824    /// The pubkey to send transactions fees to.
825    collector_id: Pubkey,
826
827    /// Fees that have been collected
828    collector_fees: AtomicU64,
829
830    /// Track cluster signature throughput and adjust fee rate
831    pub(crate) fee_rate_governor: FeeRateGovernor,
832
833    /// Rent that has been collected
834    collected_rent: AtomicU64,
835
836    /// latest rent collector, knows the epoch
837    rent_collector: RentCollector,
838
839    /// initialized from genesis
840    pub(crate) epoch_schedule: EpochSchedule,
841
842    /// inflation specs
843    inflation: Arc<RwLock<Inflation>>,
844
845    /// cache of vote_account and stake_account state for this fork
846    stakes_cache: StakesCache,
847
848    /// staked nodes on epoch boundaries, saved off when a bank.slot() is at
849    ///   a leader schedule calculation boundary
850    epoch_stakes: HashMap<Epoch, EpochStakes>,
851
852    /// A boolean reflecting whether any entries were recorded into the PoH
853    /// stream for the slot == self.slot
854    is_delta: AtomicBool,
855
856    /// Protocol-level rewards that were distributed by this bank
857    pub rewards: RwLock<Vec<(Pubkey, RewardInfo)>>,
858
859    pub cluster_type: Option<ClusterType>,
860
861    pub lazy_rent_collection: AtomicBool,
862
863    // this is temporary field only to remove rewards_pool entirely
864    pub rewards_pool_pubkeys: Arc<HashSet<Pubkey>>,
865
866    transaction_debug_keys: Option<Arc<HashSet<Pubkey>>>,
867
868    // Global configuration for how transaction logs should be collected across all banks
869    pub transaction_log_collector_config: Arc<RwLock<TransactionLogCollectorConfig>>,
870
871    // Logs from transactions that this Bank executed collected according to the criteria in
872    // `transaction_log_collector_config`
873    pub transaction_log_collector: Arc<RwLock<TransactionLogCollector>>,
874
875    pub feature_set: Arc<FeatureSet>,
876
877    /// Set of reserved account keys that cannot be write locked
878    reserved_account_keys: Arc<ReservedAccountKeys>,
879
880    /// callback function only to be called when dropping and should only be called once
881    pub drop_callback: RwLock<OptionalDropCallback>,
882
883    pub freeze_started: AtomicBool,
884
885    vote_only_bank: bool,
886
887    cost_tracker: RwLock<CostTracker>,
888
889    /// The initial accounts data size at the start of this Bank, before processing any transactions/etc
890    accounts_data_size_initial: u64,
891    /// The change to accounts data size in this Bank, due on-chain events (i.e. transactions)
892    accounts_data_size_delta_on_chain: AtomicI64,
893    /// The change to accounts data size in this Bank, due to off-chain events (i.e. rent collection)
894    accounts_data_size_delta_off_chain: AtomicI64,
895
896    /// until the skipped rewrites feature is activated, it is possible to skip rewrites and still include
897    /// the account hash of the accounts that would have been rewritten as bank hash expects.
898    skipped_rewrites: Mutex<HashMap<Pubkey, AccountHash>>,
899
900    epoch_reward_status: EpochRewardStatus,
901
902    transaction_processor: TransactionBatchProcessor<BankForks>,
903
904    check_program_modification_slot: bool,
905
906    /// Collected fee details
907    collector_fee_details: RwLock<CollectorFeeDetails>,
908
909    /// The compute budget to use for transaction execution.
910    compute_budget: Option<ComputeBudget>,
911
912    /// The max number of accounts that a transaction may lock.
913    transaction_account_lock_limit: Option<usize>,
914
915    /// Fee structure to use for assessing transaction fees.
916    fee_structure: FeeStructure,
917
918    /// blockhash and bank_hash overrides keyed by slot for simulated block production.
919    /// This _field_ was needed to be DCOU-ed to avoid 2 locks per bank freezing...
920    #[cfg(feature = "dev-context-only-utils")]
921    hash_overrides: Arc<Mutex<HashOverrides>>,
922
923    /// The lattice hash of all accounts
924    ///
925    /// The value is only meaningful after freezing.
926    accounts_lt_hash: Mutex<AccountsLtHash>,
927
928    /// A cache of *the initial state* of accounts modified in this slot
929    ///
930    /// The accounts lt hash needs both the initial and final state of each
931    /// account that was modified in this slot.  Cache the initial state here.
932    ///
933    /// Note: The initial state must be strictly from an ancestor,
934    /// and not an intermediate state within this slot.
935    cache_for_accounts_lt_hash: DashMap<Pubkey, AccountsLtHashCacheValue, ahash::RandomState>,
936
937    /// Stats related to the accounts lt hash
938    stats_for_accounts_lt_hash: AccountsLtHashStats,
939
940    /// The unique identifier for the corresponding block for this bank.
941    /// None for banks that have not yet completed replay or for leader banks as we cannot populate block_id
942    /// until bankless leader. Can be computed directly from shreds without needing to execute transactions.
943    block_id: RwLock<Option<Hash>>,
944
945    /// Accounts stats for computing the bank hash
946    bank_hash_stats: AtomicBankHashStats,
947}
948
949#[derive(Debug)]
950struct VoteReward {
951    vote_account: AccountSharedData,
952    commission: u8,
953    vote_rewards: u64,
954    vote_needs_store: bool,
955}
956
957type VoteRewards = DashMap<Pubkey, VoteReward>;
958
959#[derive(Debug, Default)]
960pub struct NewBankOptions {
961    pub vote_only_bank: bool,
962}
963
964#[cfg(feature = "dev-context-only-utils")]
965#[derive(Debug)]
966pub struct BankTestConfig {
967    pub accounts_db_config: AccountsDbConfig,
968}
969
970#[cfg(feature = "dev-context-only-utils")]
971impl Default for BankTestConfig {
972    fn default() -> Self {
973        Self {
974            accounts_db_config: ACCOUNTS_DB_CONFIG_FOR_TESTING,
975        }
976    }
977}
978
979#[derive(Debug)]
980struct PrevEpochInflationRewards {
981    validator_rewards: u64,
982    prev_epoch_duration_in_years: f64,
983    validator_rate: f64,
984    foundation_rate: f64,
985}
986
987#[derive(Debug, Default, PartialEq)]
988pub struct ProcessedTransactionCounts {
989    pub processed_transactions_count: u64,
990    pub processed_non_vote_transactions_count: u64,
991    pub processed_with_successful_result_count: u64,
992    pub signature_count: u64,
993}
994
995/// Account stats for computing the bank hash
996/// This struct is serialized and stored in the snapshot.
997#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
998#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
999pub struct BankHashStats {
1000    pub num_updated_accounts: u64,
1001    pub num_removed_accounts: u64,
1002    pub num_lamports_stored: u64,
1003    pub total_data_len: u64,
1004    pub num_executable_accounts: u64,
1005}
1006
1007impl BankHashStats {
1008    pub fn update<T: ReadableAccount>(&mut self, account: &T) {
1009        if account.lamports() == 0 {
1010            self.num_removed_accounts += 1;
1011        } else {
1012            self.num_updated_accounts += 1;
1013        }
1014        self.total_data_len = self
1015            .total_data_len
1016            .wrapping_add(account.data().len() as u64);
1017        if account.executable() {
1018            self.num_executable_accounts += 1;
1019        }
1020        self.num_lamports_stored = self.num_lamports_stored.wrapping_add(account.lamports());
1021    }
1022    pub fn accumulate(&mut self, other: &BankHashStats) {
1023        self.num_updated_accounts += other.num_updated_accounts;
1024        self.num_removed_accounts += other.num_removed_accounts;
1025        self.total_data_len = self.total_data_len.wrapping_add(other.total_data_len);
1026        self.num_lamports_stored = self
1027            .num_lamports_stored
1028            .wrapping_add(other.num_lamports_stored);
1029        self.num_executable_accounts += other.num_executable_accounts;
1030    }
1031}
1032
1033#[derive(Debug, Default)]
1034pub struct AtomicBankHashStats {
1035    pub num_updated_accounts: AtomicU64,
1036    pub num_removed_accounts: AtomicU64,
1037    pub num_lamports_stored: AtomicU64,
1038    pub total_data_len: AtomicU64,
1039    pub num_executable_accounts: AtomicU64,
1040}
1041
1042impl AtomicBankHashStats {
1043    pub fn new(stat: &BankHashStats) -> Self {
1044        AtomicBankHashStats {
1045            num_updated_accounts: AtomicU64::new(stat.num_updated_accounts),
1046            num_removed_accounts: AtomicU64::new(stat.num_removed_accounts),
1047            num_lamports_stored: AtomicU64::new(stat.num_lamports_stored),
1048            total_data_len: AtomicU64::new(stat.total_data_len),
1049            num_executable_accounts: AtomicU64::new(stat.num_executable_accounts),
1050        }
1051    }
1052
1053    pub fn accumulate(&self, other: &BankHashStats) {
1054        self.num_updated_accounts
1055            .fetch_add(other.num_updated_accounts, Relaxed);
1056        self.num_removed_accounts
1057            .fetch_add(other.num_removed_accounts, Relaxed);
1058        self.total_data_len.fetch_add(other.total_data_len, Relaxed);
1059        self.num_lamports_stored
1060            .fetch_add(other.num_lamports_stored, Relaxed);
1061        self.num_executable_accounts
1062            .fetch_add(other.num_executable_accounts, Relaxed);
1063    }
1064
1065    pub fn load(&self) -> BankHashStats {
1066        BankHashStats {
1067            num_updated_accounts: self.num_updated_accounts.load(Relaxed),
1068            num_removed_accounts: self.num_removed_accounts.load(Relaxed),
1069            num_lamports_stored: self.num_lamports_stored.load(Relaxed),
1070            total_data_len: self.total_data_len.load(Relaxed),
1071            num_executable_accounts: self.num_executable_accounts.load(Relaxed),
1072        }
1073    }
1074}
1075
1076impl Bank {
1077    fn default_with_accounts(accounts: Accounts) -> Self {
1078        let mut bank = Self {
1079            skipped_rewrites: Mutex::default(),
1080            rc: BankRc::new(accounts),
1081            status_cache: Arc::<RwLock<BankStatusCache>>::default(),
1082            blockhash_queue: RwLock::<BlockhashQueue>::default(),
1083            ancestors: Ancestors::default(),
1084            hash: RwLock::<Hash>::default(),
1085            parent_hash: Hash::default(),
1086            parent_slot: Slot::default(),
1087            hard_forks: Arc::<RwLock<HardForks>>::default(),
1088            transaction_count: AtomicU64::default(),
1089            non_vote_transaction_count_since_restart: AtomicU64::default(),
1090            transaction_error_count: AtomicU64::default(),
1091            transaction_entries_count: AtomicU64::default(),
1092            transactions_per_entry_max: AtomicU64::default(),
1093            tick_height: AtomicU64::default(),
1094            signature_count: AtomicU64::default(),
1095            capitalization: AtomicU64::default(),
1096            max_tick_height: u64::default(),
1097            hashes_per_tick: Option::<u64>::default(),
1098            ticks_per_slot: u64::default(),
1099            ns_per_slot: u128::default(),
1100            genesis_creation_time: UnixTimestamp::default(),
1101            slots_per_year: f64::default(),
1102            slot: Slot::default(),
1103            bank_id: BankId::default(),
1104            epoch: Epoch::default(),
1105            block_height: u64::default(),
1106            collector_id: Pubkey::default(),
1107            collector_fees: AtomicU64::default(),
1108            fee_rate_governor: FeeRateGovernor::default(),
1109            collected_rent: AtomicU64::default(),
1110            rent_collector: RentCollector::default(),
1111            epoch_schedule: EpochSchedule::default(),
1112            inflation: Arc::<RwLock<Inflation>>::default(),
1113            stakes_cache: StakesCache::default(),
1114            epoch_stakes: HashMap::<Epoch, EpochStakes>::default(),
1115            is_delta: AtomicBool::default(),
1116            rewards: RwLock::<Vec<(Pubkey, RewardInfo)>>::default(),
1117            cluster_type: Option::<ClusterType>::default(),
1118            lazy_rent_collection: AtomicBool::default(),
1119            rewards_pool_pubkeys: Arc::<HashSet<Pubkey>>::default(),
1120            transaction_debug_keys: Option::<Arc<HashSet<Pubkey>>>::default(),
1121            transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
1122            ),
1123            transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
1124            feature_set: Arc::<FeatureSet>::default(),
1125            reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
1126            drop_callback: RwLock::new(OptionalDropCallback(None)),
1127            freeze_started: AtomicBool::default(),
1128            vote_only_bank: false,
1129            cost_tracker: RwLock::<CostTracker>::default(),
1130            accounts_data_size_initial: 0,
1131            accounts_data_size_delta_on_chain: AtomicI64::new(0),
1132            accounts_data_size_delta_off_chain: AtomicI64::new(0),
1133            epoch_reward_status: EpochRewardStatus::default(),
1134            transaction_processor: TransactionBatchProcessor::default(),
1135            check_program_modification_slot: false,
1136            collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1137            compute_budget: None,
1138            transaction_account_lock_limit: None,
1139            fee_structure: FeeStructure::default(),
1140            #[cfg(feature = "dev-context-only-utils")]
1141            hash_overrides: Arc::new(Mutex::new(HashOverrides::default())),
1142            accounts_lt_hash: Mutex::new(AccountsLtHash(LtHash::identity())),
1143            cache_for_accounts_lt_hash: DashMap::default(),
1144            stats_for_accounts_lt_hash: AccountsLtHashStats::default(),
1145            block_id: RwLock::new(None),
1146            bank_hash_stats: AtomicBankHashStats::default(),
1147        };
1148
1149        bank.transaction_processor =
1150            TransactionBatchProcessor::new_uninitialized(bank.slot, bank.epoch);
1151
1152        let accounts_data_size_initial = bank.get_total_accounts_stats().unwrap().data_len as u64;
1153        bank.accounts_data_size_initial = accounts_data_size_initial;
1154
1155        bank
1156    }
1157
1158    #[allow(clippy::too_many_arguments)]
1159    pub fn new_with_paths(
1160        genesis_config: &GenesisConfig,
1161        runtime_config: Arc<RuntimeConfig>,
1162        paths: Vec<PathBuf>,
1163        debug_keys: Option<Arc<HashSet<Pubkey>>>,
1164        additional_builtins: Option<&[BuiltinPrototype]>,
1165        debug_do_not_add_builtins: bool,
1166        accounts_db_config: Option<AccountsDbConfig>,
1167        accounts_update_notifier: Option<AccountsUpdateNotifier>,
1168        #[allow(unused)] collector_id_for_tests: Option<Pubkey>,
1169        exit: Arc<AtomicBool>,
1170        #[allow(unused)] genesis_hash: Option<Hash>,
1171        #[allow(unused)] feature_set: Option<FeatureSet>,
1172    ) -> Self {
1173        let accounts_db =
1174            AccountsDb::new_with_config(paths, accounts_db_config, accounts_update_notifier, exit);
1175        let accounts = Accounts::new(Arc::new(accounts_db));
1176        let mut bank = Self::default_with_accounts(accounts);
1177        bank.ancestors = Ancestors::from(vec![bank.slot()]);
1178        bank.compute_budget = runtime_config.compute_budget;
1179        bank.transaction_account_lock_limit = runtime_config.transaction_account_lock_limit;
1180        bank.transaction_debug_keys = debug_keys;
1181        bank.cluster_type = Some(genesis_config.cluster_type);
1182
1183        #[cfg(feature = "dev-context-only-utils")]
1184        {
1185            bank.feature_set = Arc::new(feature_set.unwrap_or_default());
1186        }
1187
1188        #[cfg(not(feature = "dev-context-only-utils"))]
1189        bank.process_genesis_config(genesis_config);
1190        #[cfg(feature = "dev-context-only-utils")]
1191        bank.process_genesis_config(genesis_config, collector_id_for_tests, genesis_hash);
1192
1193        bank.finish_init(
1194            genesis_config,
1195            additional_builtins,
1196            debug_do_not_add_builtins,
1197        );
1198
1199        // genesis needs stakes for all epochs up to the epoch implied by
1200        //  slot = 0 and genesis configuration
1201        {
1202            let stakes = bank.stakes_cache.stakes().clone();
1203            let stakes = Arc::new(StakesEnum::from(stakes));
1204            for epoch in 0..=bank.get_leader_schedule_epoch(bank.slot) {
1205                bank.epoch_stakes
1206                    .insert(epoch, EpochStakes::new(stakes.clone(), epoch));
1207            }
1208            bank.update_stake_history(None);
1209        }
1210        bank.update_clock(None);
1211        bank.update_rent();
1212        bank.update_epoch_schedule();
1213        bank.update_recent_blockhashes();
1214        bank.update_last_restart_slot();
1215        bank.transaction_processor
1216            .fill_missing_sysvar_cache_entries(&bank);
1217        bank
1218    }
1219
1220    /// Create a new bank that points to an immutable checkpoint of another bank.
1221    pub fn new_from_parent(parent: Arc<Bank>, collector_id: &Pubkey, slot: Slot) -> Self {
1222        Self::_new_from_parent(
1223            parent,
1224            collector_id,
1225            slot,
1226            null_tracer(),
1227            NewBankOptions::default(),
1228        )
1229    }
1230
1231    pub fn new_from_parent_with_options(
1232        parent: Arc<Bank>,
1233        collector_id: &Pubkey,
1234        slot: Slot,
1235        new_bank_options: NewBankOptions,
1236    ) -> Self {
1237        Self::_new_from_parent(parent, collector_id, slot, null_tracer(), new_bank_options)
1238    }
1239
1240    pub fn new_from_parent_with_tracer(
1241        parent: Arc<Bank>,
1242        collector_id: &Pubkey,
1243        slot: Slot,
1244        reward_calc_tracer: impl RewardCalcTracer,
1245    ) -> Self {
1246        Self::_new_from_parent(
1247            parent,
1248            collector_id,
1249            slot,
1250            Some(reward_calc_tracer),
1251            NewBankOptions::default(),
1252        )
1253    }
1254
1255    fn get_rent_collector_from(rent_collector: &RentCollector, epoch: Epoch) -> RentCollector {
1256        rent_collector.clone_with_epoch(epoch)
1257    }
1258
1259    fn _new_from_parent(
1260        parent: Arc<Bank>,
1261        collector_id: &Pubkey,
1262        slot: Slot,
1263        reward_calc_tracer: Option<impl RewardCalcTracer>,
1264        new_bank_options: NewBankOptions,
1265    ) -> Self {
1266        let mut time = Measure::start("bank::new_from_parent");
1267        let NewBankOptions { vote_only_bank } = new_bank_options;
1268
1269        parent.freeze();
1270        assert_ne!(slot, parent.slot());
1271
1272        let epoch_schedule = parent.epoch_schedule().clone();
1273        let epoch = epoch_schedule.get_epoch(slot);
1274
1275        let (rc, bank_rc_creation_time_us) = measure_us!({
1276            let accounts_db = Arc::clone(&parent.rc.accounts.accounts_db);
1277            BankRc {
1278                accounts: Arc::new(Accounts::new(accounts_db)),
1279                parent: RwLock::new(Some(Arc::clone(&parent))),
1280                bank_id_generator: Arc::clone(&parent.rc.bank_id_generator),
1281            }
1282        });
1283
1284        let (status_cache, status_cache_time_us) = measure_us!(Arc::clone(&parent.status_cache));
1285
1286        let (fee_rate_governor, fee_components_time_us) = measure_us!(
1287            FeeRateGovernor::new_derived(&parent.fee_rate_governor, parent.signature_count())
1288        );
1289
1290        let bank_id = rc.bank_id_generator.fetch_add(1, Relaxed) + 1;
1291        let (blockhash_queue, blockhash_queue_time_us) =
1292            measure_us!(RwLock::new(parent.blockhash_queue.read().unwrap().clone()));
1293
1294        let (stakes_cache, stakes_cache_time_us) =
1295            measure_us!(StakesCache::new(parent.stakes_cache.stakes().clone()));
1296
1297        let (epoch_stakes, epoch_stakes_time_us) = measure_us!(parent.epoch_stakes.clone());
1298
1299        let (transaction_processor, builtin_program_ids_time_us) = measure_us!(
1300            TransactionBatchProcessor::new_from(&parent.transaction_processor, slot, epoch)
1301        );
1302
1303        let (rewards_pool_pubkeys, rewards_pool_pubkeys_time_us) =
1304            measure_us!(parent.rewards_pool_pubkeys.clone());
1305
1306        let (transaction_debug_keys, transaction_debug_keys_time_us) =
1307            measure_us!(parent.transaction_debug_keys.clone());
1308
1309        let (transaction_log_collector_config, transaction_log_collector_config_time_us) =
1310            measure_us!(parent.transaction_log_collector_config.clone());
1311
1312        let (feature_set, feature_set_time_us) = measure_us!(parent.feature_set.clone());
1313
1314        let accounts_data_size_initial = parent.load_accounts_data_size();
1315        let mut new = Self {
1316            skipped_rewrites: Mutex::default(),
1317            rc,
1318            status_cache,
1319            slot,
1320            bank_id,
1321            epoch,
1322            blockhash_queue,
1323
1324            // TODO: clean this up, so much special-case copying...
1325            hashes_per_tick: parent.hashes_per_tick,
1326            ticks_per_slot: parent.ticks_per_slot,
1327            ns_per_slot: parent.ns_per_slot,
1328            genesis_creation_time: parent.genesis_creation_time,
1329            slots_per_year: parent.slots_per_year,
1330            epoch_schedule,
1331            collected_rent: AtomicU64::new(0),
1332            rent_collector: Self::get_rent_collector_from(&parent.rent_collector, epoch),
1333            max_tick_height: slot
1334                .checked_add(1)
1335                .expect("max tick height addition overflowed")
1336                .checked_mul(parent.ticks_per_slot)
1337                .expect("max tick height multiplication overflowed"),
1338            block_height: parent
1339                .block_height
1340                .checked_add(1)
1341                .expect("block height addition overflowed"),
1342            fee_rate_governor,
1343            capitalization: AtomicU64::new(parent.capitalization()),
1344            vote_only_bank,
1345            inflation: parent.inflation.clone(),
1346            transaction_count: AtomicU64::new(parent.transaction_count()),
1347            non_vote_transaction_count_since_restart: AtomicU64::new(
1348                parent.non_vote_transaction_count_since_restart(),
1349            ),
1350            transaction_error_count: AtomicU64::new(0),
1351            transaction_entries_count: AtomicU64::new(0),
1352            transactions_per_entry_max: AtomicU64::new(0),
1353            // we will .clone_with_epoch() this soon after stake data update; so just .clone() for now
1354            stakes_cache,
1355            epoch_stakes,
1356            parent_hash: parent.hash(),
1357            parent_slot: parent.slot(),
1358            collector_id: *collector_id,
1359            collector_fees: AtomicU64::new(0),
1360            ancestors: Ancestors::default(),
1361            hash: RwLock::new(Hash::default()),
1362            is_delta: AtomicBool::new(false),
1363            tick_height: AtomicU64::new(parent.tick_height.load(Relaxed)),
1364            signature_count: AtomicU64::new(0),
1365            hard_forks: parent.hard_forks.clone(),
1366            rewards: RwLock::new(vec![]),
1367            cluster_type: parent.cluster_type,
1368            lazy_rent_collection: AtomicBool::new(parent.lazy_rent_collection.load(Relaxed)),
1369            rewards_pool_pubkeys,
1370            transaction_debug_keys,
1371            transaction_log_collector_config,
1372            transaction_log_collector: Arc::new(RwLock::new(TransactionLogCollector::default())),
1373            feature_set: Arc::clone(&feature_set),
1374            reserved_account_keys: parent.reserved_account_keys.clone(),
1375            drop_callback: RwLock::new(OptionalDropCallback(
1376                parent
1377                    .drop_callback
1378                    .read()
1379                    .unwrap()
1380                    .0
1381                    .as_ref()
1382                    .map(|drop_callback| drop_callback.clone_box()),
1383            )),
1384            freeze_started: AtomicBool::new(false),
1385            cost_tracker: RwLock::new(parent.read_cost_tracker().unwrap().new_from_parent_limits()),
1386            accounts_data_size_initial,
1387            accounts_data_size_delta_on_chain: AtomicI64::new(0),
1388            accounts_data_size_delta_off_chain: AtomicI64::new(0),
1389            epoch_reward_status: parent.epoch_reward_status.clone(),
1390            transaction_processor,
1391            check_program_modification_slot: false,
1392            collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1393            compute_budget: parent.compute_budget,
1394            transaction_account_lock_limit: parent.transaction_account_lock_limit,
1395            fee_structure: parent.fee_structure.clone(),
1396            #[cfg(feature = "dev-context-only-utils")]
1397            hash_overrides: parent.hash_overrides.clone(),
1398            accounts_lt_hash: Mutex::new(parent.accounts_lt_hash.lock().unwrap().clone()),
1399            cache_for_accounts_lt_hash: DashMap::default(),
1400            stats_for_accounts_lt_hash: AccountsLtHashStats::default(),
1401            block_id: RwLock::new(None),
1402            bank_hash_stats: AtomicBankHashStats::default(),
1403        };
1404
1405        let (_, ancestors_time_us) = measure_us!({
1406            let mut ancestors = Vec::with_capacity(1 + new.parents().len());
1407            ancestors.push(new.slot());
1408            new.parents().iter().for_each(|p| {
1409                ancestors.push(p.slot());
1410            });
1411            new.ancestors = Ancestors::from(ancestors);
1412        });
1413
1414        // Following code may touch AccountsDb, requiring proper ancestors
1415        let (_, update_epoch_time_us) = measure_us!({
1416            if parent.epoch() < new.epoch() {
1417                new.process_new_epoch(
1418                    parent.epoch(),
1419                    parent.slot(),
1420                    parent.block_height(),
1421                    reward_calc_tracer,
1422                );
1423            } else {
1424                // Save a snapshot of stakes for use in consensus and stake weighted networking
1425                let leader_schedule_epoch = new.epoch_schedule().get_leader_schedule_epoch(slot);
1426                new.update_epoch_stakes(leader_schedule_epoch);
1427            }
1428            new.distribute_partitioned_epoch_rewards();
1429        });
1430
1431        let (_epoch, slot_index) = new.epoch_schedule.get_epoch_and_slot_index(new.slot);
1432        let slots_in_epoch = new.epoch_schedule.get_slots_in_epoch(new.epoch);
1433
1434        let (_, cache_preparation_time_us) = measure_us!(new
1435            .transaction_processor
1436            .prepare_program_cache_for_upcoming_feature_set(
1437                &new,
1438                &new.compute_active_feature_set(true).0,
1439                &new.compute_budget.unwrap_or_default(),
1440                slot_index,
1441                slots_in_epoch,
1442            ));
1443
1444        // Update sysvars before processing transactions
1445        let (_, update_sysvars_time_us) = measure_us!({
1446            new.update_slot_hashes();
1447            new.update_stake_history(Some(parent.epoch()));
1448            new.update_clock(Some(parent.epoch()));
1449            new.update_last_restart_slot()
1450        });
1451
1452        let (_, fill_sysvar_cache_time_us) = measure_us!(new
1453            .transaction_processor
1454            .fill_missing_sysvar_cache_entries(&new));
1455
1456        let (num_accounts_modified_this_slot, populate_cache_for_accounts_lt_hash_us) = new
1457            .is_accounts_lt_hash_enabled()
1458            .then(|| {
1459                measure_us!({
1460                    // The cache for accounts lt hash needs to be made aware of accounts modified
1461                    // before transaction processing begins.  Otherwise we may calculate the wrong
1462                    // accounts lt hash due to having the wrong initial state of the account.  The
1463                    // lt hash cache's initial state must always be from an ancestor, and cannot be
1464                    // an intermediate state within this Bank's slot.  If the lt hash cache has the
1465                    // wrong initial account state, we'll mix out the wrong lt hash value, and thus
1466                    // have the wrong overall accounts lt hash, and diverge.
1467                    let accounts_modified_this_slot =
1468                        new.rc.accounts.accounts_db.get_pubkeys_for_slot(slot);
1469                    let num_accounts_modified_this_slot = accounts_modified_this_slot.len();
1470                    for pubkey in accounts_modified_this_slot {
1471                        new.cache_for_accounts_lt_hash
1472                            .entry(pubkey)
1473                            .or_insert(AccountsLtHashCacheValue::BankNew);
1474                    }
1475                    num_accounts_modified_this_slot
1476                })
1477            })
1478            .unzip();
1479
1480        time.stop();
1481        report_new_bank_metrics(
1482            slot,
1483            parent.slot(),
1484            new.block_height,
1485            num_accounts_modified_this_slot,
1486            NewBankTimings {
1487                bank_rc_creation_time_us,
1488                total_elapsed_time_us: time.as_us(),
1489                status_cache_time_us,
1490                fee_components_time_us,
1491                blockhash_queue_time_us,
1492                stakes_cache_time_us,
1493                epoch_stakes_time_us,
1494                builtin_program_ids_time_us,
1495                rewards_pool_pubkeys_time_us,
1496                executor_cache_time_us: 0,
1497                transaction_debug_keys_time_us,
1498                transaction_log_collector_config_time_us,
1499                feature_set_time_us,
1500                ancestors_time_us,
1501                update_epoch_time_us,
1502                cache_preparation_time_us,
1503                update_sysvars_time_us,
1504                fill_sysvar_cache_time_us,
1505                populate_cache_for_accounts_lt_hash_us,
1506            },
1507        );
1508
1509        report_loaded_programs_stats(
1510            &parent
1511                .transaction_processor
1512                .program_cache
1513                .read()
1514                .unwrap()
1515                .stats,
1516            parent.slot(),
1517        );
1518
1519        new.transaction_processor
1520            .program_cache
1521            .write()
1522            .unwrap()
1523            .stats
1524            .reset();
1525
1526        new
1527    }
1528
1529    pub fn set_fork_graph_in_program_cache(&self, fork_graph: Weak<RwLock<BankForks>>) {
1530        self.transaction_processor
1531            .program_cache
1532            .write()
1533            .unwrap()
1534            .set_fork_graph(fork_graph);
1535    }
1536
1537    pub fn prune_program_cache(&self, new_root_slot: Slot, new_root_epoch: Epoch) {
1538        self.transaction_processor
1539            .program_cache
1540            .write()
1541            .unwrap()
1542            .prune(new_root_slot, new_root_epoch);
1543    }
1544
1545    pub fn prune_program_cache_by_deployment_slot(&self, deployment_slot: Slot) {
1546        self.transaction_processor
1547            .program_cache
1548            .write()
1549            .unwrap()
1550            .prune_by_deployment_slot(deployment_slot);
1551    }
1552
1553    /// Epoch in which the new cooldown warmup rate for stake was activated
1554    pub fn new_warmup_cooldown_rate_epoch(&self) -> Option<Epoch> {
1555        self.feature_set
1556            .new_warmup_cooldown_rate_epoch(&self.epoch_schedule)
1557    }
1558
1559    /// process for the start of a new epoch
1560    fn process_new_epoch(
1561        &mut self,
1562        parent_epoch: Epoch,
1563        parent_slot: Slot,
1564        parent_height: u64,
1565        reward_calc_tracer: Option<impl RewardCalcTracer>,
1566    ) {
1567        let epoch = self.epoch();
1568        let slot = self.slot();
1569        let (thread_pool, thread_pool_time_us) = measure_us!(ThreadPoolBuilder::new()
1570            .thread_name(|i| format!("solBnkNewEpch{i:02}"))
1571            .build()
1572            .expect("new rayon threadpool"));
1573
1574        let (_, apply_feature_activations_time_us) = measure_us!(thread_pool.install(|| {
1575            self.apply_feature_activations(ApplyFeatureActivationsCaller::NewFromParent, false)
1576        }));
1577
1578        // Add new entry to stakes.stake_history, set appropriate epoch and
1579        // update vote accounts with warmed up stakes before saving a
1580        // snapshot of stakes in epoch stakes
1581        let (_, activate_epoch_time_us) = measure_us!(self.stakes_cache.activate_epoch(
1582            epoch,
1583            &thread_pool,
1584            self.new_warmup_cooldown_rate_epoch()
1585        ));
1586
1587        // Save a snapshot of stakes for use in consensus and stake weighted networking
1588        let leader_schedule_epoch = self.epoch_schedule.get_leader_schedule_epoch(slot);
1589        let (_, update_epoch_stakes_time_us) =
1590            measure_us!(self.update_epoch_stakes(leader_schedule_epoch));
1591
1592        let mut rewards_metrics = RewardsMetrics::default();
1593        // After saving a snapshot of stakes, apply stake rewards and commission
1594        let (_, update_rewards_with_thread_pool_time_us) = measure_us!(self
1595            .begin_partitioned_rewards(
1596                reward_calc_tracer,
1597                &thread_pool,
1598                parent_epoch,
1599                parent_slot,
1600                parent_height,
1601                &mut rewards_metrics,
1602            ));
1603
1604        report_new_epoch_metrics(
1605            epoch,
1606            slot,
1607            parent_slot,
1608            NewEpochTimings {
1609                thread_pool_time_us,
1610                apply_feature_activations_time_us,
1611                activate_epoch_time_us,
1612                update_epoch_stakes_time_us,
1613                update_rewards_with_thread_pool_time_us,
1614            },
1615            rewards_metrics,
1616        );
1617    }
1618
1619    pub fn byte_limit_for_scans(&self) -> Option<usize> {
1620        self.rc
1621            .accounts
1622            .accounts_db
1623            .accounts_index
1624            .scan_results_limit_bytes
1625    }
1626
1627    pub fn proper_ancestors_set(&self) -> HashSet<Slot> {
1628        HashSet::from_iter(self.proper_ancestors())
1629    }
1630
1631    /// Returns all ancestors excluding self.slot.
1632    pub(crate) fn proper_ancestors(&self) -> impl Iterator<Item = Slot> + '_ {
1633        self.ancestors
1634            .keys()
1635            .into_iter()
1636            .filter(move |slot| *slot != self.slot)
1637    }
1638
1639    pub fn set_callback(&self, callback: Option<Box<dyn DropCallback + Send + Sync>>) {
1640        *self.drop_callback.write().unwrap() = OptionalDropCallback(callback);
1641    }
1642
1643    pub fn vote_only_bank(&self) -> bool {
1644        self.vote_only_bank
1645    }
1646
1647    /// Like `new_from_parent` but additionally:
1648    /// * Doesn't assume that the parent is anywhere near `slot`, parent could be millions of slots
1649    ///   in the past
1650    /// * Adjusts the new bank's tick height to avoid having to run PoH for millions of slots
1651    /// * Freezes the new bank, assuming that the user will `Bank::new_from_parent` from this bank
1652    /// * Calculates and sets the epoch accounts hash from the parent
1653    pub fn warp_from_parent(
1654        parent: Arc<Bank>,
1655        collector_id: &Pubkey,
1656        slot: Slot,
1657        data_source: CalcAccountsHashDataSource,
1658    ) -> Self {
1659        parent.freeze();
1660        parent
1661            .rc
1662            .accounts
1663            .accounts_db
1664            .epoch_accounts_hash_manager
1665            .set_in_flight(parent.slot());
1666        let accounts_hash = parent.update_accounts_hash(data_source, false, true);
1667        let epoch_accounts_hash = accounts_hash.into();
1668        parent
1669            .rc
1670            .accounts
1671            .accounts_db
1672            .epoch_accounts_hash_manager
1673            .set_valid(epoch_accounts_hash, parent.slot());
1674
1675        let parent_timestamp = parent.clock().unix_timestamp;
1676        let mut new = Bank::new_from_parent(parent, collector_id, slot);
1677        new.apply_feature_activations(ApplyFeatureActivationsCaller::WarpFromParent, false);
1678        new.update_epoch_stakes(new.epoch_schedule().get_epoch(slot));
1679        new.tick_height.store(new.max_tick_height(), Relaxed);
1680
1681        let mut clock = new.clock();
1682        clock.epoch_start_timestamp = parent_timestamp;
1683        clock.unix_timestamp = parent_timestamp;
1684        new.update_sysvar_account(&sysvar::clock::id(), |account| {
1685            create_account(
1686                &clock,
1687                new.inherit_specially_retained_account_fields(account),
1688            )
1689        });
1690        new.transaction_processor
1691            .fill_missing_sysvar_cache_entries(&new);
1692        new.freeze();
1693        new
1694    }
1695
1696    /// Create a bank from explicit arguments and deserialized fields from snapshot
1697    pub(crate) fn new_from_fields(
1698        bank_rc: BankRc,
1699        genesis_config: &GenesisConfig,
1700        runtime_config: Arc<RuntimeConfig>,
1701        fields: BankFieldsToDeserialize,
1702        debug_keys: Option<Arc<HashSet<Pubkey>>>,
1703        additional_builtins: Option<&[BuiltinPrototype]>,
1704        debug_do_not_add_builtins: bool,
1705        accounts_data_size_initial: u64,
1706    ) -> Self {
1707        let now = Instant::now();
1708        let ancestors = Ancestors::from(&fields.ancestors);
1709        // For backward compatibility, we can only serialize and deserialize
1710        // Stakes<Delegation> in BankFieldsTo{Serialize,Deserialize}. But Bank
1711        // caches Stakes<StakeAccount>. Below Stakes<StakeAccount> is obtained
1712        // from Stakes<Delegation> by reading the full account state from
1713        // accounts-db. Note that it is crucial that these accounts are loaded
1714        // at the right slot and match precisely with serialized Delegations.
1715        //
1716        // Note that we are disabling the read cache while we populate the stakes cache.
1717        // The stakes accounts will not be expected to be loaded again.
1718        // If we populate the read cache with these loads, then we'll just soon have to evict these.
1719        let (stakes, stakes_time) = measure_time!(Stakes::new(&fields.stakes, |pubkey| {
1720            let (account, _slot) = bank_rc
1721                .accounts
1722                .load_with_fixed_root_do_not_populate_read_cache(&ancestors, pubkey)?;
1723            Some(account)
1724        })
1725        .expect(
1726            "Stakes cache is inconsistent with accounts-db. This can indicate \
1727            a corrupted snapshot or bugs in cached accounts or accounts-db.",
1728        ));
1729        info!("Loading Stakes took: {stakes_time}");
1730        let stakes_accounts_load_duration = now.elapsed();
1731        let mut bank = Self {
1732            skipped_rewrites: Mutex::default(),
1733            rc: bank_rc,
1734            status_cache: Arc::<RwLock<BankStatusCache>>::default(),
1735            blockhash_queue: RwLock::new(fields.blockhash_queue),
1736            ancestors,
1737            hash: RwLock::new(fields.hash),
1738            parent_hash: fields.parent_hash,
1739            parent_slot: fields.parent_slot,
1740            hard_forks: Arc::new(RwLock::new(fields.hard_forks)),
1741            transaction_count: AtomicU64::new(fields.transaction_count),
1742            non_vote_transaction_count_since_restart: AtomicU64::default(),
1743            transaction_error_count: AtomicU64::default(),
1744            transaction_entries_count: AtomicU64::default(),
1745            transactions_per_entry_max: AtomicU64::default(),
1746            tick_height: AtomicU64::new(fields.tick_height),
1747            signature_count: AtomicU64::new(fields.signature_count),
1748            capitalization: AtomicU64::new(fields.capitalization),
1749            max_tick_height: fields.max_tick_height,
1750            hashes_per_tick: fields.hashes_per_tick,
1751            ticks_per_slot: fields.ticks_per_slot,
1752            ns_per_slot: fields.ns_per_slot,
1753            genesis_creation_time: fields.genesis_creation_time,
1754            slots_per_year: fields.slots_per_year,
1755            slot: fields.slot,
1756            bank_id: 0,
1757            epoch: fields.epoch,
1758            block_height: fields.block_height,
1759            collector_id: fields.collector_id,
1760            collector_fees: AtomicU64::new(fields.collector_fees),
1761            fee_rate_governor: fields.fee_rate_governor,
1762            collected_rent: AtomicU64::new(fields.collected_rent),
1763            // clone()-ing is needed to consider a gated behavior in rent_collector
1764            rent_collector: Self::get_rent_collector_from(&fields.rent_collector, fields.epoch),
1765            epoch_schedule: fields.epoch_schedule,
1766            inflation: Arc::new(RwLock::new(fields.inflation)),
1767            stakes_cache: StakesCache::new(stakes),
1768            epoch_stakes: fields.epoch_stakes,
1769            is_delta: AtomicBool::new(fields.is_delta),
1770            rewards: RwLock::new(vec![]),
1771            cluster_type: Some(genesis_config.cluster_type),
1772            lazy_rent_collection: AtomicBool::default(),
1773            rewards_pool_pubkeys: Arc::<HashSet<Pubkey>>::default(),
1774            transaction_debug_keys: debug_keys,
1775            transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
1776            ),
1777            transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
1778            feature_set: Arc::<FeatureSet>::default(),
1779            reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
1780            drop_callback: RwLock::new(OptionalDropCallback(None)),
1781            freeze_started: AtomicBool::new(fields.hash != Hash::default()),
1782            vote_only_bank: false,
1783            cost_tracker: RwLock::new(CostTracker::default()),
1784            accounts_data_size_initial,
1785            accounts_data_size_delta_on_chain: AtomicI64::new(0),
1786            accounts_data_size_delta_off_chain: AtomicI64::new(0),
1787            epoch_reward_status: EpochRewardStatus::default(),
1788            transaction_processor: TransactionBatchProcessor::default(),
1789            check_program_modification_slot: false,
1790            // collector_fee_details is not serialized to snapshot
1791            collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1792            compute_budget: runtime_config.compute_budget,
1793            transaction_account_lock_limit: runtime_config.transaction_account_lock_limit,
1794            fee_structure: FeeStructure::default(),
1795            #[cfg(feature = "dev-context-only-utils")]
1796            hash_overrides: Arc::new(Mutex::new(HashOverrides::default())),
1797            accounts_lt_hash: Mutex::new(AccountsLtHash(LtHash([0xBAD1; LtHash::NUM_ELEMENTS]))),
1798            cache_for_accounts_lt_hash: DashMap::default(),
1799            stats_for_accounts_lt_hash: AccountsLtHashStats::default(),
1800            block_id: RwLock::new(None),
1801            bank_hash_stats: AtomicBankHashStats::new(&fields.bank_hash_stats),
1802        };
1803
1804        bank.transaction_processor =
1805            TransactionBatchProcessor::new_uninitialized(bank.slot, bank.epoch);
1806
1807        let thread_pool = ThreadPoolBuilder::new()
1808            .thread_name(|i| format!("solBnkNewFlds{i:02}"))
1809            .build()
1810            .expect("new rayon threadpool");
1811        bank.recalculate_partitioned_rewards(null_tracer(), &thread_pool);
1812
1813        bank.finish_init(
1814            genesis_config,
1815            additional_builtins,
1816            debug_do_not_add_builtins,
1817        );
1818        bank.transaction_processor
1819            .fill_missing_sysvar_cache_entries(&bank);
1820        bank.rebuild_skipped_rewrites();
1821
1822        let mut calculate_accounts_lt_hash_duration = None;
1823        if let Some(accounts_lt_hash) = fields.accounts_lt_hash {
1824            *bank.accounts_lt_hash.get_mut().unwrap() = accounts_lt_hash;
1825        } else {
1826            // Use the accounts lt hash from the snapshot, if present, otherwise calculate it.
1827            // When the feature gate is enabled, the snapshot *must* contain an accounts lt hash.
1828            assert!(
1829                !bank
1830                    .feature_set
1831                    .is_active(&feature_set::accounts_lt_hash::id()),
1832                "snapshot must have an accounts lt hash if the feature is enabled",
1833            );
1834            if bank.is_accounts_lt_hash_enabled() {
1835                info!(
1836                    "Calculating the accounts lt hash for slot {}...",
1837                    bank.slot(),
1838                );
1839                let (ancestors, slot) = if bank.is_frozen() {
1840                    // Loading from a snapshot necessarily means this slot was rooted, and thus
1841                    // the bank has been frozen.  So when calculating the accounts lt hash,
1842                    // do it based on *this slot*, not our parent, since
1843                    // update_accounts_lt_hash() will not be called on us again.
1844                    (bank.ancestors.clone(), bank.slot())
1845                } else {
1846                    // If the bank is not frozen (e.g. if called from tests), then when this bank
1847                    // is frozen later it will call `update_accounts_lt_hash()`.  Therefore, we
1848                    // must calculate the accounts lt hash *here* based on *our parent*, so that
1849                    // the accounts lt hash is correct after freezing.
1850                    let parent_ancestors = {
1851                        let mut ancestors = bank.ancestors.clone();
1852                        ancestors.remove(&bank.slot());
1853                        ancestors
1854                    };
1855                    (parent_ancestors, bank.parent_slot)
1856                };
1857                let (accounts_lt_hash, duration) = meas_dur!({
1858                    thread_pool.install(|| {
1859                        bank.rc
1860                            .accounts
1861                            .accounts_db
1862                            .calculate_accounts_lt_hash_at_startup_from_index(&ancestors, slot)
1863                    })
1864                });
1865                calculate_accounts_lt_hash_duration = Some(duration);
1866                *bank.accounts_lt_hash.get_mut().unwrap() = accounts_lt_hash;
1867                info!(
1868                    "Calculating the accounts lt hash for slot {}... \
1869                     Done in {duration:?}, accounts_lt_hash checksum: {}",
1870                    bank.slot(),
1871                    bank.accounts_lt_hash.get_mut().unwrap().0.checksum(),
1872                );
1873            }
1874        }
1875
1876        // Sanity assertions between bank snapshot and genesis config
1877        // Consider removing from serializable bank state
1878        // (BankFieldsToSerialize/BankFieldsToDeserialize) and initializing
1879        // from the passed in genesis_config instead (as new()/new_with_paths() already do)
1880        assert_eq!(
1881            bank.genesis_creation_time, genesis_config.creation_time,
1882            "Bank snapshot genesis creation time does not match genesis.bin creation time. \
1883             The snapshot and genesis.bin might pertain to different clusters"
1884        );
1885        assert_eq!(bank.ticks_per_slot, genesis_config.ticks_per_slot);
1886        assert_eq!(
1887            bank.ns_per_slot,
1888            genesis_config.poh_config.target_tick_duration.as_nanos()
1889                * genesis_config.ticks_per_slot as u128
1890        );
1891        assert_eq!(bank.max_tick_height, (bank.slot + 1) * bank.ticks_per_slot);
1892        assert_eq!(
1893            bank.slots_per_year,
1894            years_as_slots(
1895                1.0,
1896                &genesis_config.poh_config.target_tick_duration,
1897                bank.ticks_per_slot,
1898            )
1899        );
1900        assert_eq!(bank.epoch_schedule, genesis_config.epoch_schedule);
1901        assert_eq!(bank.epoch, bank.epoch_schedule.get_epoch(bank.slot));
1902
1903        datapoint_info!(
1904            "bank-new-from-fields",
1905            (
1906                "accounts_data_len-from-snapshot",
1907                fields.accounts_data_len as i64,
1908                i64
1909            ),
1910            (
1911                "accounts_data_len-from-generate_index",
1912                accounts_data_size_initial as i64,
1913                i64
1914            ),
1915            (
1916                "stakes_accounts_load_duration_us",
1917                stakes_accounts_load_duration.as_micros(),
1918                i64
1919            ),
1920            (
1921                "calculate_accounts_lt_hash_us",
1922                calculate_accounts_lt_hash_duration.as_ref().map(Duration::as_micros),
1923                Option<i64>
1924            ),
1925        );
1926        bank
1927    }
1928
1929    /// Return subset of bank fields representing serializable state
1930    pub(crate) fn get_fields_to_serialize(&self) -> BankFieldsToSerialize {
1931        let (epoch_stakes, versioned_epoch_stakes) = split_epoch_stakes(self.epoch_stakes.clone());
1932        BankFieldsToSerialize {
1933            blockhash_queue: self.blockhash_queue.read().unwrap().clone(),
1934            ancestors: AncestorsForSerialization::from(&self.ancestors),
1935            hash: *self.hash.read().unwrap(),
1936            parent_hash: self.parent_hash,
1937            parent_slot: self.parent_slot,
1938            hard_forks: self.hard_forks.read().unwrap().clone(),
1939            transaction_count: self.transaction_count.load(Relaxed),
1940            tick_height: self.tick_height.load(Relaxed),
1941            signature_count: self.signature_count.load(Relaxed),
1942            capitalization: self.capitalization.load(Relaxed),
1943            max_tick_height: self.max_tick_height,
1944            hashes_per_tick: self.hashes_per_tick,
1945            ticks_per_slot: self.ticks_per_slot,
1946            ns_per_slot: self.ns_per_slot,
1947            genesis_creation_time: self.genesis_creation_time,
1948            slots_per_year: self.slots_per_year,
1949            slot: self.slot,
1950            epoch: self.epoch,
1951            block_height: self.block_height,
1952            collector_id: self.collector_id,
1953            collector_fees: self.collector_fees.load(Relaxed),
1954            fee_rate_governor: self.fee_rate_governor.clone(),
1955            collected_rent: self.collected_rent.load(Relaxed),
1956            rent_collector: self.rent_collector.clone(),
1957            epoch_schedule: self.epoch_schedule.clone(),
1958            inflation: *self.inflation.read().unwrap(),
1959            stakes: StakesEnum::from(self.stakes_cache.stakes().clone()),
1960            epoch_stakes,
1961            is_delta: self.is_delta.load(Relaxed),
1962            accounts_data_len: self.load_accounts_data_size(),
1963            versioned_epoch_stakes,
1964            accounts_lt_hash: self
1965                .is_accounts_lt_hash_enabled()
1966                .then(|| self.accounts_lt_hash.lock().unwrap().clone()),
1967        }
1968    }
1969
1970    pub fn collector_id(&self) -> &Pubkey {
1971        &self.collector_id
1972    }
1973
1974    pub fn genesis_creation_time(&self) -> UnixTimestamp {
1975        self.genesis_creation_time
1976    }
1977
1978    pub fn slot(&self) -> Slot {
1979        self.slot
1980    }
1981
1982    pub fn bank_id(&self) -> BankId {
1983        self.bank_id
1984    }
1985
1986    pub fn epoch(&self) -> Epoch {
1987        self.epoch
1988    }
1989
1990    pub fn first_normal_epoch(&self) -> Epoch {
1991        self.epoch_schedule().first_normal_epoch
1992    }
1993
1994    pub fn freeze_lock(&self) -> RwLockReadGuard<Hash> {
1995        self.hash.read().unwrap()
1996    }
1997
1998    pub fn hash(&self) -> Hash {
1999        *self.hash.read().unwrap()
2000    }
2001
2002    pub fn is_frozen(&self) -> bool {
2003        *self.hash.read().unwrap() != Hash::default()
2004    }
2005
2006    pub fn freeze_started(&self) -> bool {
2007        self.freeze_started.load(Relaxed)
2008    }
2009
2010    pub fn status_cache_ancestors(&self) -> Vec<u64> {
2011        let mut roots = self.status_cache.read().unwrap().roots().clone();
2012        let min = roots.iter().min().cloned().unwrap_or(0);
2013        for ancestor in self.ancestors.keys() {
2014            if ancestor >= min {
2015                roots.insert(ancestor);
2016            }
2017        }
2018
2019        let mut ancestors: Vec<_> = roots.into_iter().collect();
2020        #[allow(clippy::stable_sort_primitive)]
2021        ancestors.sort();
2022        ancestors
2023    }
2024
2025    /// computed unix_timestamp at this slot height
2026    pub fn unix_timestamp_from_genesis(&self) -> i64 {
2027        self.genesis_creation_time.saturating_add(
2028            (self.slot as u128)
2029                .saturating_mul(self.ns_per_slot)
2030                .saturating_div(1_000_000_000) as i64,
2031        )
2032    }
2033
2034    fn update_sysvar_account<F>(&self, pubkey: &Pubkey, updater: F)
2035    where
2036        F: Fn(&Option<AccountSharedData>) -> AccountSharedData,
2037    {
2038        let old_account = self.get_account_with_fixed_root(pubkey);
2039        let mut new_account = updater(&old_account);
2040
2041        // When new sysvar comes into existence (with RENT_UNADJUSTED_INITIAL_BALANCE lamports),
2042        // this code ensures that the sysvar's balance is adjusted to be rent-exempt.
2043        //
2044        // More generally, this code always re-calculates for possible sysvar data size change,
2045        // although there is no such sysvars currently.
2046        self.adjust_sysvar_balance_for_rent(&mut new_account);
2047        self.store_account_and_update_capitalization(pubkey, &new_account);
2048    }
2049
2050    fn inherit_specially_retained_account_fields(
2051        &self,
2052        old_account: &Option<AccountSharedData>,
2053    ) -> InheritableAccountFields {
2054        const RENT_UNADJUSTED_INITIAL_BALANCE: u64 = 1;
2055
2056        (
2057            old_account
2058                .as_ref()
2059                .map(|a| a.lamports())
2060                .unwrap_or(RENT_UNADJUSTED_INITIAL_BALANCE),
2061            old_account
2062                .as_ref()
2063                .map(|a| a.rent_epoch())
2064                .unwrap_or(INITIAL_RENT_EPOCH),
2065        )
2066    }
2067
2068    pub fn clock(&self) -> sysvar::clock::Clock {
2069        from_account(&self.get_account(&sysvar::clock::id()).unwrap_or_default())
2070            .unwrap_or_default()
2071    }
2072
2073    fn update_clock(&self, parent_epoch: Option<Epoch>) {
2074        let mut unix_timestamp = self.clock().unix_timestamp;
2075        // set epoch_start_timestamp to None to warp timestamp
2076        let epoch_start_timestamp = {
2077            let epoch = if let Some(epoch) = parent_epoch {
2078                epoch
2079            } else {
2080                self.epoch()
2081            };
2082            let first_slot_in_epoch = self.epoch_schedule().get_first_slot_in_epoch(epoch);
2083            Some((first_slot_in_epoch, self.clock().epoch_start_timestamp))
2084        };
2085        let max_allowable_drift = MaxAllowableDrift {
2086            fast: MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST,
2087            slow: MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
2088        };
2089
2090        let ancestor_timestamp = self.clock().unix_timestamp;
2091        if let Some(timestamp_estimate) =
2092            self.get_timestamp_estimate(max_allowable_drift, epoch_start_timestamp)
2093        {
2094            unix_timestamp = timestamp_estimate;
2095            if timestamp_estimate < ancestor_timestamp {
2096                unix_timestamp = ancestor_timestamp;
2097            }
2098        }
2099        datapoint_info!(
2100            "bank-timestamp-correction",
2101            ("slot", self.slot(), i64),
2102            ("from_genesis", self.unix_timestamp_from_genesis(), i64),
2103            ("corrected", unix_timestamp, i64),
2104            ("ancestor_timestamp", ancestor_timestamp, i64),
2105        );
2106        let mut epoch_start_timestamp =
2107            // On epoch boundaries, update epoch_start_timestamp
2108            if parent_epoch.is_some() && parent_epoch.unwrap() != self.epoch() {
2109                unix_timestamp
2110            } else {
2111                self.clock().epoch_start_timestamp
2112            };
2113        if self.slot == 0 {
2114            unix_timestamp = self.unix_timestamp_from_genesis();
2115            epoch_start_timestamp = self.unix_timestamp_from_genesis();
2116        }
2117        let clock = sysvar::clock::Clock {
2118            slot: self.slot,
2119            epoch_start_timestamp,
2120            epoch: self.epoch_schedule().get_epoch(self.slot),
2121            leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
2122            unix_timestamp,
2123        };
2124        self.update_sysvar_account(&sysvar::clock::id(), |account| {
2125            create_account(
2126                &clock,
2127                self.inherit_specially_retained_account_fields(account),
2128            )
2129        });
2130    }
2131
2132    pub fn update_last_restart_slot(&self) {
2133        let feature_flag = self
2134            .feature_set
2135            .is_active(&feature_set::last_restart_slot_sysvar::id());
2136
2137        if feature_flag {
2138            // First, see what the currently stored last restart slot is. This
2139            // account may not exist yet if the feature was just activated.
2140            let current_last_restart_slot = self
2141                .get_account(&sysvar::last_restart_slot::id())
2142                .and_then(|account| {
2143                    let lrs: Option<LastRestartSlot> = from_account(&account);
2144                    lrs
2145                })
2146                .map(|account| account.last_restart_slot);
2147
2148            let last_restart_slot = {
2149                let slot = self.slot;
2150                let hard_forks_r = self.hard_forks.read().unwrap();
2151
2152                // Only consider hard forks <= this bank's slot to avoid prematurely applying
2153                // a hard fork that is set to occur in the future.
2154                hard_forks_r
2155                    .iter()
2156                    .rev()
2157                    .find(|(hard_fork, _)| *hard_fork <= slot)
2158                    .map(|(slot, _)| *slot)
2159                    .unwrap_or(0)
2160            };
2161
2162            // Only need to write if the last restart has changed
2163            if current_last_restart_slot != Some(last_restart_slot) {
2164                self.update_sysvar_account(&sysvar::last_restart_slot::id(), |account| {
2165                    create_account(
2166                        &LastRestartSlot { last_restart_slot },
2167                        self.inherit_specially_retained_account_fields(account),
2168                    )
2169                });
2170            }
2171        }
2172    }
2173
2174    pub fn set_sysvar_for_tests<T>(&self, sysvar: &T)
2175    where
2176        T: Sysvar + SysvarId,
2177    {
2178        self.update_sysvar_account(&T::id(), |account| {
2179            create_account(
2180                sysvar,
2181                self.inherit_specially_retained_account_fields(account),
2182            )
2183        });
2184        // Simply force fill sysvar cache rather than checking which sysvar was
2185        // actually updated since tests don't need to be optimized for performance.
2186        self.transaction_processor.reset_sysvar_cache();
2187        self.transaction_processor
2188            .fill_missing_sysvar_cache_entries(self);
2189    }
2190
2191    fn update_slot_history(&self) {
2192        self.update_sysvar_account(&sysvar::slot_history::id(), |account| {
2193            let mut slot_history = account
2194                .as_ref()
2195                .map(|account| from_account::<SlotHistory, _>(account).unwrap())
2196                .unwrap_or_default();
2197            slot_history.add(self.slot());
2198            create_account(
2199                &slot_history,
2200                self.inherit_specially_retained_account_fields(account),
2201            )
2202        });
2203    }
2204
2205    fn update_slot_hashes(&self) {
2206        self.update_sysvar_account(&sysvar::slot_hashes::id(), |account| {
2207            let mut slot_hashes = account
2208                .as_ref()
2209                .map(|account| from_account::<SlotHashes, _>(account).unwrap())
2210                .unwrap_or_default();
2211            slot_hashes.add(self.parent_slot, self.parent_hash);
2212            create_account(
2213                &slot_hashes,
2214                self.inherit_specially_retained_account_fields(account),
2215            )
2216        });
2217    }
2218
2219    pub fn get_slot_history(&self) -> SlotHistory {
2220        from_account(&self.get_account(&sysvar::slot_history::id()).unwrap()).unwrap()
2221    }
2222
2223    fn update_epoch_stakes(&mut self, leader_schedule_epoch: Epoch) {
2224        // update epoch_stakes cache
2225        //  if my parent didn't populate for this staker's epoch, we've
2226        //  crossed a boundary
2227        if !self.epoch_stakes.contains_key(&leader_schedule_epoch) {
2228            self.epoch_stakes.retain(|&epoch, _| {
2229                epoch >= leader_schedule_epoch.saturating_sub(MAX_LEADER_SCHEDULE_STAKES)
2230            });
2231            let stakes = self.stakes_cache.stakes().clone();
2232            let stakes = Arc::new(StakesEnum::from(stakes));
2233            let new_epoch_stakes = EpochStakes::new(stakes, leader_schedule_epoch);
2234            info!(
2235                "new epoch stakes, epoch: {}, total_stake: {}",
2236                leader_schedule_epoch,
2237                new_epoch_stakes.total_stake(),
2238            );
2239
2240            // It is expensive to log the details of epoch stakes. Only log them at "trace"
2241            // level for debugging purpose.
2242            if log::log_enabled!(log::Level::Trace) {
2243                let vote_stakes: HashMap<_, _> = self
2244                    .stakes_cache
2245                    .stakes()
2246                    .vote_accounts()
2247                    .delegated_stakes()
2248                    .map(|(pubkey, stake)| (*pubkey, stake))
2249                    .collect();
2250                trace!("new epoch stakes, stakes: {vote_stakes:#?}");
2251            }
2252            self.epoch_stakes
2253                .insert(leader_schedule_epoch, new_epoch_stakes);
2254        }
2255    }
2256
2257    #[cfg(feature = "dev-context-only-utils")]
2258    pub fn set_epoch_stakes_for_test(&mut self, epoch: Epoch, stakes: EpochStakes) {
2259        self.epoch_stakes.insert(epoch, stakes);
2260    }
2261
2262    fn update_rent(&self) {
2263        self.update_sysvar_account(&sysvar::rent::id(), |account| {
2264            create_account(
2265                &self.rent_collector.rent,
2266                self.inherit_specially_retained_account_fields(account),
2267            )
2268        });
2269    }
2270
2271    fn update_epoch_schedule(&self) {
2272        self.update_sysvar_account(&sysvar::epoch_schedule::id(), |account| {
2273            create_account(
2274                self.epoch_schedule(),
2275                self.inherit_specially_retained_account_fields(account),
2276            )
2277        });
2278    }
2279
2280    fn update_stake_history(&self, epoch: Option<Epoch>) {
2281        if epoch == Some(self.epoch()) {
2282            return;
2283        }
2284        // if I'm the first Bank in an epoch, ensure stake_history is updated
2285        self.update_sysvar_account(&sysvar::stake_history::id(), |account| {
2286            create_account::<sysvar::stake_history::StakeHistory>(
2287                self.stakes_cache.stakes().history(),
2288                self.inherit_specially_retained_account_fields(account),
2289            )
2290        });
2291    }
2292
2293    pub fn epoch_duration_in_years(&self, prev_epoch: Epoch) -> f64 {
2294        // period: time that has passed as a fraction of a year, basically the length of
2295        //  an epoch as a fraction of a year
2296        //  calculated as: slots_elapsed / (slots / year)
2297        self.epoch_schedule().get_slots_in_epoch(prev_epoch) as f64 / self.slots_per_year
2298    }
2299
2300    // Calculates the starting-slot for inflation from the activation slot.
2301    // This method assumes that `pico_inflation` will be enabled before `full_inflation`, giving
2302    // precedence to the latter. However, since `pico_inflation` is fixed-rate Inflation, should
2303    // `pico_inflation` be enabled 2nd, the incorrect start slot provided here should have no
2304    // effect on the inflation calculation.
2305    fn get_inflation_start_slot(&self) -> Slot {
2306        let mut slots = self
2307            .feature_set
2308            .full_inflation_features_enabled()
2309            .iter()
2310            .filter_map(|id| self.feature_set.activated_slot(id))
2311            .collect::<Vec<_>>();
2312        slots.sort_unstable();
2313        slots.first().cloned().unwrap_or_else(|| {
2314            self.feature_set
2315                .activated_slot(&feature_set::pico_inflation::id())
2316                .unwrap_or(0)
2317        })
2318    }
2319
2320    fn get_inflation_num_slots(&self) -> u64 {
2321        let inflation_activation_slot = self.get_inflation_start_slot();
2322        // Normalize inflation_start to align with the start of rewards accrual.
2323        let inflation_start_slot = self.epoch_schedule().get_first_slot_in_epoch(
2324            self.epoch_schedule()
2325                .get_epoch(inflation_activation_slot)
2326                .saturating_sub(1),
2327        );
2328        self.epoch_schedule().get_first_slot_in_epoch(self.epoch()) - inflation_start_slot
2329    }
2330
2331    pub fn slot_in_year_for_inflation(&self) -> f64 {
2332        let num_slots = self.get_inflation_num_slots();
2333
2334        // calculated as: num_slots / (slots / year)
2335        num_slots as f64 / self.slots_per_year
2336    }
2337
2338    fn calculate_previous_epoch_inflation_rewards(
2339        &self,
2340        prev_epoch_capitalization: u64,
2341        prev_epoch: Epoch,
2342    ) -> PrevEpochInflationRewards {
2343        let slot_in_year = self.slot_in_year_for_inflation();
2344        let (validator_rate, foundation_rate) = {
2345            let inflation = self.inflation.read().unwrap();
2346            (
2347                (*inflation).validator(slot_in_year),
2348                (*inflation).foundation(slot_in_year),
2349            )
2350        };
2351
2352        let prev_epoch_duration_in_years = self.epoch_duration_in_years(prev_epoch);
2353        let validator_rewards = (validator_rate
2354            * prev_epoch_capitalization as f64
2355            * prev_epoch_duration_in_years) as u64;
2356
2357        PrevEpochInflationRewards {
2358            validator_rewards,
2359            prev_epoch_duration_in_years,
2360            validator_rate,
2361            foundation_rate,
2362        }
2363    }
2364
2365    fn assert_validator_rewards_paid(&self, validator_rewards_paid: u64) {
2366        assert_eq!(
2367            validator_rewards_paid,
2368            u64::try_from(
2369                self.rewards
2370                    .read()
2371                    .unwrap()
2372                    .par_iter()
2373                    .map(|(_address, reward_info)| {
2374                        match reward_info.reward_type {
2375                            RewardType::Voting | RewardType::Staking => reward_info.lamports,
2376                            _ => 0,
2377                        }
2378                    })
2379                    .sum::<i64>()
2380            )
2381            .unwrap()
2382        );
2383    }
2384
2385    fn filter_stake_delegations<'a>(
2386        &self,
2387        stakes: &'a Stakes<StakeAccount<Delegation>>,
2388    ) -> Vec<(&'a Pubkey, &'a StakeAccount<Delegation>)> {
2389        if self
2390            .feature_set
2391            .is_active(&feature_set::stake_minimum_delegation_for_rewards::id())
2392        {
2393            let num_stake_delegations = stakes.stake_delegations().len();
2394            let min_stake_delegation =
2395                solana_stake_program::get_minimum_delegation(&self.feature_set)
2396                    .max(LAMPORTS_PER_SOL);
2397
2398            let (stake_delegations, filter_time_us) = measure_us!(stakes
2399                .stake_delegations()
2400                .iter()
2401                .filter(|(_stake_pubkey, cached_stake_account)| {
2402                    cached_stake_account.delegation().stake >= min_stake_delegation
2403                })
2404                .collect::<Vec<_>>());
2405
2406            datapoint_info!(
2407                "stake_account_filter_time",
2408                ("filter_time_us", filter_time_us, i64),
2409                ("num_stake_delegations_before", num_stake_delegations, i64),
2410                ("num_stake_delegations_after", stake_delegations.len(), i64)
2411            );
2412            stake_delegations
2413        } else {
2414            stakes.stake_delegations().iter().collect()
2415        }
2416    }
2417
2418    /// return reward info for each vote account
2419    /// return account data for each vote account that needs to be stored
2420    /// This return value is a little awkward at the moment so that downstream existing code in the non-partitioned rewards code path can be re-used without duplication or modification.
2421    /// This function is copied from the existing code path's `store_vote_accounts`.
2422    /// The primary differences:
2423    /// - we want this fn to have no side effects (such as actually storing vote accounts) so that we
2424    ///   can compare the expected results with the current code path
2425    /// - we want to be able to batch store the vote accounts later for improved performance/cache updating
2426    fn calc_vote_accounts_to_store(
2427        vote_account_rewards: DashMap<Pubkey, VoteReward>,
2428    ) -> VoteRewardsAccounts {
2429        let len = vote_account_rewards.len();
2430        let mut result = VoteRewardsAccounts {
2431            rewards: Vec::with_capacity(len),
2432            accounts_to_store: Vec::with_capacity(len),
2433        };
2434        vote_account_rewards.into_iter().for_each(
2435            |(
2436                vote_pubkey,
2437                VoteReward {
2438                    mut vote_account,
2439                    commission,
2440                    vote_rewards,
2441                    vote_needs_store,
2442                },
2443            )| {
2444                if let Err(err) = vote_account.checked_add_lamports(vote_rewards) {
2445                    debug!("reward redemption failed for {}: {:?}", vote_pubkey, err);
2446                    return;
2447                }
2448
2449                result.rewards.push((
2450                    vote_pubkey,
2451                    RewardInfo {
2452                        reward_type: RewardType::Voting,
2453                        lamports: vote_rewards as i64,
2454                        post_balance: vote_account.lamports(),
2455                        commission: Some(commission),
2456                    },
2457                ));
2458                result
2459                    .accounts_to_store
2460                    .push(vote_needs_store.then_some(vote_account));
2461            },
2462        );
2463        result
2464    }
2465
2466    fn update_reward_history(
2467        &self,
2468        stake_rewards: StakeRewards,
2469        mut vote_rewards: Vec<(Pubkey, RewardInfo)>,
2470    ) {
2471        let additional_reserve = stake_rewards.len() + vote_rewards.len();
2472        let mut rewards = self.rewards.write().unwrap();
2473        rewards.reserve(additional_reserve);
2474        rewards.append(&mut vote_rewards);
2475        stake_rewards
2476            .into_iter()
2477            .filter(|x| x.get_stake_reward() > 0)
2478            .for_each(|x| rewards.push((x.stake_pubkey, x.stake_reward_info)));
2479    }
2480
2481    fn update_recent_blockhashes_locked(&self, locked_blockhash_queue: &BlockhashQueue) {
2482        #[allow(deprecated)]
2483        self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
2484            let recent_blockhash_iter = locked_blockhash_queue.get_recent_blockhashes();
2485            recent_blockhashes_account::create_account_with_data_and_fields(
2486                recent_blockhash_iter,
2487                self.inherit_specially_retained_account_fields(account),
2488            )
2489        });
2490    }
2491
2492    pub fn update_recent_blockhashes(&self) {
2493        let blockhash_queue = self.blockhash_queue.read().unwrap();
2494        self.update_recent_blockhashes_locked(&blockhash_queue);
2495    }
2496
2497    fn get_timestamp_estimate(
2498        &self,
2499        max_allowable_drift: MaxAllowableDrift,
2500        epoch_start_timestamp: Option<(Slot, UnixTimestamp)>,
2501    ) -> Option<UnixTimestamp> {
2502        let mut get_timestamp_estimate_time = Measure::start("get_timestamp_estimate");
2503        let slots_per_epoch = self.epoch_schedule().slots_per_epoch;
2504        let vote_accounts = self.vote_accounts();
2505        let recent_timestamps = vote_accounts.iter().filter_map(|(pubkey, (_, account))| {
2506            let vote_state = account.vote_state();
2507            let slot_delta = self.slot().checked_sub(vote_state.last_timestamp.slot)?;
2508            (slot_delta <= slots_per_epoch).then_some({
2509                (
2510                    *pubkey,
2511                    (
2512                        vote_state.last_timestamp.slot,
2513                        vote_state.last_timestamp.timestamp,
2514                    ),
2515                )
2516            })
2517        });
2518        let slot_duration = Duration::from_nanos(self.ns_per_slot as u64);
2519        let epoch = self.epoch_schedule().get_epoch(self.slot());
2520        let stakes = self.epoch_vote_accounts(epoch)?;
2521        let stake_weighted_timestamp = calculate_stake_weighted_timestamp(
2522            recent_timestamps,
2523            stakes,
2524            self.slot(),
2525            slot_duration,
2526            epoch_start_timestamp,
2527            max_allowable_drift,
2528            self.feature_set
2529                .is_active(&feature_set::warp_timestamp_again::id()),
2530        );
2531        get_timestamp_estimate_time.stop();
2532        datapoint_info!(
2533            "bank-timestamp",
2534            (
2535                "get_timestamp_estimate_us",
2536                get_timestamp_estimate_time.as_us(),
2537                i64
2538            ),
2539        );
2540        stake_weighted_timestamp
2541    }
2542
2543    /// Recalculates the bank hash
2544    ///
2545    /// This is used by ledger-tool when creating a snapshot, which
2546    /// recalcuates the bank hash.
2547    ///
2548    /// Note that the account state is *not* allowed to change by rehashing.
2549    /// If modifying accounts in ledger-tool is needed, create a new bank.
2550    pub fn rehash(&self) {
2551        let get_delta_hash = || {
2552            (!self
2553                .feature_set
2554                .is_active(&feature_set::remove_accounts_delta_hash::id()))
2555            .then(|| {
2556                self.rc
2557                    .accounts
2558                    .accounts_db
2559                    .get_accounts_delta_hash(self.slot())
2560            })
2561            .flatten()
2562        };
2563
2564        let mut hash = self.hash.write().unwrap();
2565        let curr_accounts_delta_hash = get_delta_hash();
2566        let new = self.hash_internal_state();
2567        if let Some(curr_accounts_delta_hash) = curr_accounts_delta_hash {
2568            let new_accounts_delta_hash = get_delta_hash().unwrap();
2569            assert_eq!(
2570                new_accounts_delta_hash, curr_accounts_delta_hash,
2571                "rehashing is not allowed to change the account state",
2572            );
2573        }
2574        if new != *hash {
2575            warn!("Updating bank hash to {new}");
2576            *hash = new;
2577        }
2578    }
2579
2580    pub fn freeze(&self) {
2581        // This lock prevents any new commits from BankingStage
2582        // `Consumer::execute_and_commit_transactions_locked()` from
2583        // coming in after the last tick is observed. This is because in
2584        // BankingStage, any transaction successfully recorded in
2585        // `record_transactions()` is recorded after this `hash` lock
2586        // is grabbed. At the time of the successful record,
2587        // this means the PoH has not yet reached the last tick,
2588        // so this means freeze() hasn't been called yet. And because
2589        // BankingStage doesn't release this hash lock until both
2590        // record and commit are finished, those transactions will be
2591        // committed before this write lock can be obtained here.
2592        let mut hash = self.hash.write().unwrap();
2593        if *hash == Hash::default() {
2594            // finish up any deferred changes to account state
2595            self.collect_rent_eagerly();
2596            if self.feature_set.is_active(&reward_full_priority_fee::id()) {
2597                self.distribute_transaction_fee_details();
2598            } else {
2599                self.distribute_transaction_fees();
2600            }
2601            self.distribute_rent_fees();
2602            self.update_slot_history();
2603            self.run_incinerator();
2604
2605            // freeze is a one-way trip, idempotent
2606            self.freeze_started.store(true, Relaxed);
2607            if self.is_accounts_lt_hash_enabled() {
2608                // updating the accounts lt hash must happen *outside* of hash_internal_state() so
2609                // that rehash() can be called and *not* modify self.accounts_lt_hash.
2610                self.update_accounts_lt_hash();
2611
2612                // For lattice-hash R&D, we have a CLI arg to do extra verfication.  If set, we'll
2613                // re-calculate the accounts lt hash every slot and compare it against the value
2614                // already stored in the bank.
2615                if self
2616                    .rc
2617                    .accounts
2618                    .accounts_db
2619                    .verify_experimental_accumulator_hash
2620                {
2621                    let slot = self.slot();
2622                    info!("Verifying the accounts lt hash for slot {slot}...");
2623                    let (calculated_accounts_lt_hash, duration) = meas_dur!({
2624                        self.rc
2625                            .accounts
2626                            .accounts_db
2627                            .calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors, slot)
2628                    });
2629                    let actual_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap();
2630                    assert_eq!(
2631                        calculated_accounts_lt_hash,
2632                        *actual_accounts_lt_hash,
2633                        "Verifying the accounts lt hash for slot {slot} failed! calculated checksum: {}, actual checksum: {}",
2634                        calculated_accounts_lt_hash.0.checksum(),
2635                        actual_accounts_lt_hash.0.checksum(),
2636                    );
2637                    info!("Verifying the accounts lt hash for slot {slot}... Done successfully in {duration:?}");
2638                }
2639            }
2640            *hash = self.hash_internal_state();
2641            self.rc.accounts.accounts_db.mark_slot_frozen(self.slot());
2642        }
2643    }
2644
2645    // dangerous; don't use this; this is only needed for ledger-tool's special command
2646    #[cfg(feature = "dev-context-only-utils")]
2647    pub fn unfreeze_for_ledger_tool(&self) {
2648        self.freeze_started.store(false, Relaxed);
2649    }
2650
2651    pub fn epoch_schedule(&self) -> &EpochSchedule {
2652        &self.epoch_schedule
2653    }
2654
2655    /// squash the parent's state up into this Bank,
2656    ///   this Bank becomes a root
2657    /// Note that this function is not thread-safe. If it is called concurrently on the same bank
2658    /// by multiple threads, the end result could be inconsistent.
2659    /// Calling code does not currently call this concurrently.
2660    pub fn squash(&self) -> SquashTiming {
2661        self.freeze();
2662
2663        //this bank and all its parents are now on the rooted path
2664        let mut roots = vec![self.slot()];
2665        roots.append(&mut self.parents().iter().map(|p| p.slot()).collect());
2666
2667        let mut total_index_us = 0;
2668        let mut total_cache_us = 0;
2669        let mut total_store_us = 0;
2670
2671        let mut squash_accounts_time = Measure::start("squash_accounts_time");
2672        for slot in roots.iter().rev() {
2673            // root forks cannot be purged
2674            let add_root_timing = self.rc.accounts.add_root(*slot);
2675            total_index_us += add_root_timing.index_us;
2676            total_cache_us += add_root_timing.cache_us;
2677            total_store_us += add_root_timing.store_us;
2678        }
2679        squash_accounts_time.stop();
2680
2681        *self.rc.parent.write().unwrap() = None;
2682
2683        let mut squash_cache_time = Measure::start("squash_cache_time");
2684        roots
2685            .iter()
2686            .for_each(|slot| self.status_cache.write().unwrap().add_root(*slot));
2687        squash_cache_time.stop();
2688
2689        SquashTiming {
2690            squash_accounts_ms: squash_accounts_time.as_ms(),
2691            squash_accounts_index_ms: total_index_us / 1000,
2692            squash_accounts_cache_ms: total_cache_us / 1000,
2693            squash_accounts_store_ms: total_store_us / 1000,
2694
2695            squash_cache_ms: squash_cache_time.as_ms(),
2696        }
2697    }
2698
2699    /// Return the more recent checkpoint of this bank instance.
2700    pub fn parent(&self) -> Option<Arc<Bank>> {
2701        self.rc.parent.read().unwrap().clone()
2702    }
2703
2704    pub fn parent_slot(&self) -> Slot {
2705        self.parent_slot
2706    }
2707
2708    pub fn parent_hash(&self) -> Hash {
2709        self.parent_hash
2710    }
2711
2712    fn process_genesis_config(
2713        &mut self,
2714        genesis_config: &GenesisConfig,
2715        #[cfg(feature = "dev-context-only-utils")] collector_id_for_tests: Option<Pubkey>,
2716        #[cfg(feature = "dev-context-only-utils")] genesis_hash: Option<Hash>,
2717    ) {
2718        // Bootstrap validator collects fees until `new_from_parent` is called.
2719        self.fee_rate_governor = genesis_config.fee_rate_governor.clone();
2720
2721        for (pubkey, account) in genesis_config.accounts.iter() {
2722            assert!(
2723                self.get_account(pubkey).is_none(),
2724                "{pubkey} repeated in genesis config"
2725            );
2726            self.store_account(pubkey, &account.to_account_shared_data());
2727            self.capitalization.fetch_add(account.lamports(), Relaxed);
2728            self.accounts_data_size_initial += account.data().len() as u64;
2729        }
2730
2731        for (pubkey, account) in genesis_config.rewards_pools.iter() {
2732            assert!(
2733                self.get_account(pubkey).is_none(),
2734                "{pubkey} repeated in genesis config"
2735            );
2736            self.store_account(pubkey, &account.to_account_shared_data());
2737            self.accounts_data_size_initial += account.data().len() as u64;
2738        }
2739
2740        // After storing genesis accounts, the bank stakes cache will be warmed
2741        // up and can be used to set the collector id to the highest staked
2742        // node. If no staked nodes exist, allow fallback to an unstaked test
2743        // collector id during tests.
2744        let collector_id = self.stakes_cache.stakes().highest_staked_node().copied();
2745        #[cfg(feature = "dev-context-only-utils")]
2746        let collector_id = collector_id.or(collector_id_for_tests);
2747        self.collector_id =
2748            collector_id.expect("genesis processing failed because no staked nodes exist");
2749
2750        #[cfg(not(feature = "dev-context-only-utils"))]
2751        let genesis_hash = genesis_config.hash();
2752        #[cfg(feature = "dev-context-only-utils")]
2753        let genesis_hash = genesis_hash.unwrap_or(genesis_config.hash());
2754
2755        self.blockhash_queue
2756            .write()
2757            .unwrap()
2758            .genesis_hash(&genesis_hash, self.fee_rate_governor.lamports_per_signature);
2759
2760        self.hashes_per_tick = genesis_config.hashes_per_tick();
2761        self.ticks_per_slot = genesis_config.ticks_per_slot();
2762        self.ns_per_slot = genesis_config.ns_per_slot();
2763        self.genesis_creation_time = genesis_config.creation_time;
2764        self.max_tick_height = (self.slot + 1) * self.ticks_per_slot;
2765        self.slots_per_year = genesis_config.slots_per_year();
2766
2767        self.epoch_schedule = genesis_config.epoch_schedule.clone();
2768
2769        self.inflation = Arc::new(RwLock::new(genesis_config.inflation));
2770
2771        self.rent_collector = RentCollector::new(
2772            self.epoch,
2773            self.epoch_schedule().clone(),
2774            self.slots_per_year,
2775            genesis_config.rent.clone(),
2776        );
2777
2778        // Add additional builtin programs specified in the genesis config
2779        for (name, program_id) in &genesis_config.native_instruction_processors {
2780            self.add_builtin_account(name, program_id);
2781        }
2782    }
2783
2784    fn burn_and_purge_account(&self, program_id: &Pubkey, mut account: AccountSharedData) {
2785        let old_data_size = account.data().len();
2786        self.capitalization.fetch_sub(account.lamports(), Relaxed);
2787        // Both resetting account balance to 0 and zeroing the account data
2788        // is needed to really purge from AccountsDb and flush the Stakes cache
2789        account.set_lamports(0);
2790        account.data_as_mut_slice().fill(0);
2791        self.store_account(program_id, &account);
2792        self.calculate_and_update_accounts_data_size_delta_off_chain(old_data_size, 0);
2793    }
2794
2795    /// Add a precompiled program account
2796    pub fn add_precompiled_account(&self, program_id: &Pubkey) {
2797        self.add_precompiled_account_with_owner(program_id, native_loader::id())
2798    }
2799
2800    // Used by tests to simulate clusters with precompiles that aren't owned by the native loader
2801    fn add_precompiled_account_with_owner(&self, program_id: &Pubkey, owner: Pubkey) {
2802        if let Some(account) = self.get_account_with_fixed_root(program_id) {
2803            if account.executable() {
2804                return;
2805            } else {
2806                // malicious account is pre-occupying at program_id
2807                self.burn_and_purge_account(program_id, account);
2808            }
2809        };
2810
2811        assert!(
2812            !self.freeze_started(),
2813            "Can't change frozen bank by adding not-existing new precompiled program ({program_id}). \
2814                Maybe, inconsistent program activation is detected on snapshot restore?"
2815        );
2816
2817        // Add a bogus executable account, which will be loaded and ignored.
2818        let (lamports, rent_epoch) = self.inherit_specially_retained_account_fields(&None);
2819
2820        let account = AccountSharedData::from(Account {
2821            lamports,
2822            owner,
2823            data: vec![],
2824            executable: true,
2825            rent_epoch,
2826        });
2827        self.store_account_and_update_capitalization(program_id, &account);
2828    }
2829
2830    pub fn set_rent_burn_percentage(&mut self, burn_percent: u8) {
2831        self.rent_collector.rent.burn_percent = burn_percent;
2832    }
2833
2834    pub fn set_hashes_per_tick(&mut self, hashes_per_tick: Option<u64>) {
2835        self.hashes_per_tick = hashes_per_tick;
2836    }
2837
2838    /// Return the last block hash registered.
2839    pub fn last_blockhash(&self) -> Hash {
2840        self.blockhash_queue.read().unwrap().last_hash()
2841    }
2842
2843    pub fn last_blockhash_and_lamports_per_signature(&self) -> (Hash, u64) {
2844        let blockhash_queue = self.blockhash_queue.read().unwrap();
2845        let last_hash = blockhash_queue.last_hash();
2846        let last_lamports_per_signature = blockhash_queue
2847            .get_lamports_per_signature(&last_hash)
2848            .unwrap(); // safe so long as the BlockhashQueue is consistent
2849        (last_hash, last_lamports_per_signature)
2850    }
2851
2852    pub fn is_blockhash_valid(&self, hash: &Hash) -> bool {
2853        let blockhash_queue = self.blockhash_queue.read().unwrap();
2854        blockhash_queue.is_hash_valid_for_age(hash, MAX_PROCESSING_AGE)
2855    }
2856
2857    pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
2858        self.rent_collector.rent.minimum_balance(data_len).max(1)
2859    }
2860
2861    pub fn get_lamports_per_signature(&self) -> u64 {
2862        self.fee_rate_governor.lamports_per_signature
2863    }
2864
2865    pub fn get_lamports_per_signature_for_blockhash(&self, hash: &Hash) -> Option<u64> {
2866        let blockhash_queue = self.blockhash_queue.read().unwrap();
2867        blockhash_queue.get_lamports_per_signature(hash)
2868    }
2869
2870    pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> Option<u64> {
2871        let lamports_per_signature = {
2872            let blockhash_queue = self.blockhash_queue.read().unwrap();
2873            blockhash_queue.get_lamports_per_signature(message.recent_blockhash())
2874        }
2875        .or_else(|| {
2876            self.load_message_nonce_account(message).map(
2877                |(_nonce_address, _nonce_account, nonce_data)| {
2878                    nonce_data.get_lamports_per_signature()
2879                },
2880            )
2881        })?;
2882        Some(self.get_fee_for_message_with_lamports_per_signature(message, lamports_per_signature))
2883    }
2884
2885    /// Returns true when startup accounts hash verification has completed or never had to run in background.
2886    pub fn get_startup_verification_complete(&self) -> &Arc<AtomicBool> {
2887        &self
2888            .rc
2889            .accounts
2890            .accounts_db
2891            .verify_accounts_hash_in_bg
2892            .verified
2893    }
2894
2895    /// return true if bg hash verification is complete
2896    /// return false if bg hash verification has not completed yet
2897    /// if hash verification failed, a panic will occur
2898    pub fn is_startup_verification_complete(&self) -> bool {
2899        self.has_initial_accounts_hash_verification_completed()
2900    }
2901
2902    /// This can occur because it completed in the background
2903    /// or if the verification was run in the foreground.
2904    pub fn set_startup_verification_complete(&self) {
2905        self.set_initial_accounts_hash_verification_completed();
2906    }
2907
2908    pub fn get_fee_for_message_with_lamports_per_signature(
2909        &self,
2910        message: &impl SVMMessage,
2911        lamports_per_signature: u64,
2912    ) -> u64 {
2913        let fee_budget_limits = FeeBudgetLimits::from(
2914            process_compute_budget_instructions(
2915                message.program_instructions_iter(),
2916                &self.feature_set,
2917            )
2918            .unwrap_or_default(),
2919        );
2920        solana_fee::calculate_fee(
2921            message,
2922            lamports_per_signature == 0,
2923            self.fee_structure().lamports_per_signature,
2924            fee_budget_limits.prioritization_fee,
2925            FeeFeatures::from(self.feature_set.as_ref()),
2926        )
2927    }
2928
2929    pub fn get_blockhash_last_valid_block_height(&self, blockhash: &Hash) -> Option<Slot> {
2930        let blockhash_queue = self.blockhash_queue.read().unwrap();
2931        // This calculation will need to be updated to consider epoch boundaries if BlockhashQueue
2932        // length is made variable by epoch
2933        blockhash_queue
2934            .get_hash_age(blockhash)
2935            .map(|age| self.block_height + MAX_PROCESSING_AGE as u64 - age)
2936    }
2937
2938    pub fn confirmed_last_blockhash(&self) -> Hash {
2939        const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
2940
2941        let parents = self.parents();
2942        if parents.is_empty() {
2943            self.last_blockhash()
2944        } else {
2945            let index = NUM_BLOCKHASH_CONFIRMATIONS.min(parents.len() - 1);
2946            parents[index].last_blockhash()
2947        }
2948    }
2949
2950    /// Forget all signatures. Useful for benchmarking.
2951    pub fn clear_signatures(&self) {
2952        self.status_cache.write().unwrap().clear();
2953    }
2954
2955    pub fn clear_slot_signatures(&self, slot: Slot) {
2956        self.status_cache.write().unwrap().clear_slot_entries(slot);
2957    }
2958
2959    fn update_transaction_statuses(
2960        &self,
2961        sanitized_txs: &[impl TransactionWithMeta],
2962        processing_results: &[TransactionProcessingResult],
2963    ) {
2964        let mut status_cache = self.status_cache.write().unwrap();
2965        assert_eq!(sanitized_txs.len(), processing_results.len());
2966        for (tx, processing_result) in sanitized_txs.iter().zip(processing_results) {
2967            if let Ok(processed_tx) = &processing_result {
2968                // Add the message hash to the status cache to ensure that this message
2969                // won't be processed again with a different signature.
2970                status_cache.insert(
2971                    tx.recent_blockhash(),
2972                    tx.message_hash(),
2973                    self.slot(),
2974                    processed_tx.status(),
2975                );
2976                // Add the transaction signature to the status cache so that transaction status
2977                // can be queried by transaction signature over RPC. In the future, this should
2978                // only be added for API nodes because voting validators don't need to do this.
2979                status_cache.insert(
2980                    tx.recent_blockhash(),
2981                    tx.signature(),
2982                    self.slot(),
2983                    processed_tx.status(),
2984                );
2985            }
2986        }
2987    }
2988
2989    /// Register a new recent blockhash in the bank's recent blockhash queue. Called when a bank
2990    /// reaches its max tick height. Can be called by tests to get new blockhashes for transaction
2991    /// processing without advancing to a new bank slot.
2992    fn register_recent_blockhash(&self, blockhash: &Hash, scheduler: &InstalledSchedulerRwLock) {
2993        // This is needed because recent_blockhash updates necessitate synchronizations for
2994        // consistent tx check_age handling.
2995        BankWithScheduler::wait_for_paused_scheduler(self, scheduler);
2996
2997        // Only acquire the write lock for the blockhash queue on block boundaries because
2998        // readers can starve this write lock acquisition and ticks would be slowed down too
2999        // much if the write lock is acquired for each tick.
3000        let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3001
3002        #[cfg(feature = "dev-context-only-utils")]
3003        let blockhash_override = self
3004            .hash_overrides
3005            .lock()
3006            .unwrap()
3007            .get_blockhash_override(self.slot())
3008            .copied()
3009            .inspect(|blockhash_override| {
3010                if blockhash_override != blockhash {
3011                    info!(
3012                        "bank: slot: {}: overrode blockhash: {} with {}",
3013                        self.slot(),
3014                        blockhash,
3015                        blockhash_override
3016                    );
3017                }
3018            });
3019        #[cfg(feature = "dev-context-only-utils")]
3020        let blockhash = blockhash_override.as_ref().unwrap_or(blockhash);
3021
3022        w_blockhash_queue.register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3023        self.update_recent_blockhashes_locked(&w_blockhash_queue);
3024    }
3025
3026    // gating this under #[cfg(feature = "dev-context-only-utils")] isn't easy due to
3027    // solana-program-test's usage...
3028    pub fn register_unique_recent_blockhash_for_test(&self) {
3029        self.register_recent_blockhash(
3030            &Hash::new_unique(),
3031            &BankWithScheduler::no_scheduler_available(),
3032        )
3033    }
3034
3035    #[cfg(feature = "dev-context-only-utils")]
3036    pub fn register_recent_blockhash_for_test(
3037        &self,
3038        blockhash: &Hash,
3039        lamports_per_signature: Option<u64>,
3040    ) {
3041        // Only acquire the write lock for the blockhash queue on block boundaries because
3042        // readers can starve this write lock acquisition and ticks would be slowed down too
3043        // much if the write lock is acquired for each tick.
3044        let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3045        if let Some(lamports_per_signature) = lamports_per_signature {
3046            w_blockhash_queue.register_hash(blockhash, lamports_per_signature);
3047        } else {
3048            w_blockhash_queue
3049                .register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3050        }
3051    }
3052
3053    /// Tell the bank which Entry IDs exist on the ledger. This function assumes subsequent calls
3054    /// correspond to later entries, and will boot the oldest ones once its internal cache is full.
3055    /// Once boot, the bank will reject transactions using that `hash`.
3056    ///
3057    /// This is NOT thread safe because if tick height is updated by two different threads, the
3058    /// block boundary condition could be missed.
3059    pub fn register_tick(&self, hash: &Hash, scheduler: &InstalledSchedulerRwLock) {
3060        assert!(
3061            !self.freeze_started(),
3062            "register_tick() working on a bank that is already frozen or is undergoing freezing!"
3063        );
3064
3065        if self.is_block_boundary(self.tick_height.load(Relaxed) + 1) {
3066            self.register_recent_blockhash(hash, scheduler);
3067        }
3068
3069        // ReplayStage will start computing the accounts delta hash when it
3070        // detects the tick height has reached the boundary, so the system
3071        // needs to guarantee all account updates for the slot have been
3072        // committed before this tick height is incremented (like the blockhash
3073        // sysvar above)
3074        self.tick_height.fetch_add(1, Relaxed);
3075    }
3076
3077    #[cfg(feature = "dev-context-only-utils")]
3078    pub fn register_tick_for_test(&self, hash: &Hash) {
3079        self.register_tick(hash, &BankWithScheduler::no_scheduler_available())
3080    }
3081
3082    #[cfg(feature = "dev-context-only-utils")]
3083    pub fn register_default_tick_for_test(&self) {
3084        self.register_tick_for_test(&Hash::default())
3085    }
3086
3087    #[cfg(feature = "dev-context-only-utils")]
3088    pub fn register_unique_tick(&self) {
3089        self.register_tick_for_test(&Hash::new_unique())
3090    }
3091
3092    pub fn is_complete(&self) -> bool {
3093        self.tick_height() == self.max_tick_height()
3094    }
3095
3096    pub fn is_block_boundary(&self, tick_height: u64) -> bool {
3097        tick_height == self.max_tick_height
3098    }
3099
3100    /// Get the max number of accounts that a transaction may lock in this block
3101    pub fn get_transaction_account_lock_limit(&self) -> usize {
3102        if let Some(transaction_account_lock_limit) = self.transaction_account_lock_limit {
3103            transaction_account_lock_limit
3104        } else if self
3105            .feature_set
3106            .is_active(&feature_set::increase_tx_account_lock_limit::id())
3107        {
3108            MAX_TX_ACCOUNT_LOCKS
3109        } else {
3110            64
3111        }
3112    }
3113
3114    /// Prepare a transaction batch from a list of versioned transactions from
3115    /// an entry. Used for tests only.
3116    pub fn prepare_entry_batch(
3117        &self,
3118        txs: Vec<VersionedTransaction>,
3119    ) -> Result<TransactionBatch<RuntimeTransaction<SanitizedTransaction>>> {
3120        let sanitized_txs = txs
3121            .into_iter()
3122            .map(|tx| {
3123                RuntimeTransaction::try_create(
3124                    tx,
3125                    MessageHash::Compute,
3126                    None,
3127                    self,
3128                    self.get_reserved_account_keys(),
3129                )
3130            })
3131            .collect::<Result<Vec<_>>>()?;
3132        let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3133        let lock_results = self
3134            .rc
3135            .accounts
3136            .lock_accounts(sanitized_txs.iter(), tx_account_lock_limit);
3137        Ok(TransactionBatch::new(
3138            lock_results,
3139            self,
3140            OwnedOrBorrowed::Owned(sanitized_txs),
3141        ))
3142    }
3143
3144    /// Attempt to take locks on the accounts in a transaction batch
3145    pub fn try_lock_accounts(&self, txs: &[impl SVMMessage]) -> Vec<Result<()>> {
3146        let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3147        self.rc
3148            .accounts
3149            .lock_accounts(txs.iter(), tx_account_lock_limit)
3150    }
3151
3152    /// Prepare a locked transaction batch from a list of sanitized transactions.
3153    pub fn prepare_sanitized_batch<'a, 'b, Tx: SVMMessage>(
3154        &'a self,
3155        txs: &'b [Tx],
3156    ) -> TransactionBatch<'a, 'b, Tx> {
3157        TransactionBatch::new(
3158            self.try_lock_accounts(txs),
3159            self,
3160            OwnedOrBorrowed::Borrowed(txs),
3161        )
3162    }
3163
3164    /// Prepare a locked transaction batch from a list of sanitized transactions, and their cost
3165    /// limited packing status
3166    pub fn prepare_sanitized_batch_with_results<'a, 'b, Tx: SVMMessage>(
3167        &'a self,
3168        transactions: &'b [Tx],
3169        transaction_results: impl Iterator<Item = Result<()>>,
3170    ) -> TransactionBatch<'a, 'b, Tx> {
3171        // this lock_results could be: Ok, AccountInUse, WouldExceedBlockMaxLimit or WouldExceedAccountMaxLimit
3172        let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3173        let lock_results = self.rc.accounts.lock_accounts_with_results(
3174            transactions.iter(),
3175            transaction_results,
3176            tx_account_lock_limit,
3177        );
3178        TransactionBatch::new(lock_results, self, OwnedOrBorrowed::Borrowed(transactions))
3179    }
3180
3181    /// Prepare a transaction batch from a single transaction without locking accounts
3182    pub fn prepare_unlocked_batch_from_single_tx<'a, Tx: SVMMessage>(
3183        &'a self,
3184        transaction: &'a Tx,
3185    ) -> TransactionBatch<'a, 'a, Tx> {
3186        let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3187        let lock_result = validate_account_locks(transaction.account_keys(), tx_account_lock_limit);
3188        let mut batch = TransactionBatch::new(
3189            vec![lock_result],
3190            self,
3191            OwnedOrBorrowed::Borrowed(slice::from_ref(transaction)),
3192        );
3193        batch.set_needs_unlock(false);
3194        batch
3195    }
3196
3197    /// Run transactions against a frozen bank without committing the results
3198    pub fn simulate_transaction(
3199        &self,
3200        transaction: &impl TransactionWithMeta,
3201        enable_cpi_recording: bool,
3202    ) -> TransactionSimulationResult {
3203        assert!(self.is_frozen(), "simulation bank must be frozen");
3204
3205        self.simulate_transaction_unchecked(transaction, enable_cpi_recording)
3206    }
3207
3208    /// Run transactions against a bank without committing the results; does not check if the bank
3209    /// is frozen, enabling use in single-Bank test frameworks
3210    pub fn simulate_transaction_unchecked(
3211        &self,
3212        transaction: &impl TransactionWithMeta,
3213        enable_cpi_recording: bool,
3214    ) -> TransactionSimulationResult {
3215        let account_keys = transaction.account_keys();
3216        let number_of_accounts = account_keys.len();
3217        let account_overrides = self.get_account_overrides_for_simulation(&account_keys);
3218        let batch = self.prepare_unlocked_batch_from_single_tx(transaction);
3219        let mut timings = ExecuteTimings::default();
3220
3221        let LoadAndExecuteTransactionsOutput {
3222            mut processing_results,
3223            ..
3224        } = self.load_and_execute_transactions(
3225            &batch,
3226            // After simulation, transactions will need to be forwarded to the leader
3227            // for processing. During forwarding, the transaction could expire if the
3228            // delay is not accounted for.
3229            MAX_PROCESSING_AGE - MAX_TRANSACTION_FORWARDING_DELAY,
3230            &mut timings,
3231            &mut TransactionErrorMetrics::default(),
3232            TransactionProcessingConfig {
3233                account_overrides: Some(&account_overrides),
3234                check_program_modification_slot: self.check_program_modification_slot,
3235                compute_budget: self.compute_budget(),
3236                log_messages_bytes_limit: None,
3237                limit_to_load_programs: true,
3238                recording_config: ExecutionRecordingConfig {
3239                    enable_cpi_recording,
3240                    enable_log_recording: true,
3241                    enable_return_data_recording: true,
3242                },
3243                transaction_account_lock_limit: Some(self.get_transaction_account_lock_limit()),
3244            },
3245        );
3246
3247        let units_consumed =
3248            timings
3249                .details
3250                .per_program_timings
3251                .iter()
3252                .fold(0, |acc: u64, (_, program_timing)| {
3253                    (std::num::Saturating(acc)
3254                        + program_timing.accumulated_units
3255                        + program_timing.total_errored_units)
3256                        .0
3257                });
3258
3259        debug!("simulate_transaction: {:?}", timings);
3260
3261        let processing_result = processing_results
3262            .pop()
3263            .unwrap_or(Err(TransactionError::InvalidProgramForExecution));
3264        let (post_simulation_accounts, result, logs, return_data, inner_instructions) =
3265            match processing_result {
3266                Ok(processed_tx) => match processed_tx {
3267                    ProcessedTransaction::Executed(executed_tx) => {
3268                        let details = executed_tx.execution_details;
3269                        let post_simulation_accounts = executed_tx
3270                            .loaded_transaction
3271                            .accounts
3272                            .into_iter()
3273                            .take(number_of_accounts)
3274                            .collect::<Vec<_>>();
3275                        (
3276                            post_simulation_accounts,
3277                            details.status,
3278                            details.log_messages,
3279                            details.return_data,
3280                            details.inner_instructions,
3281                        )
3282                    }
3283                    ProcessedTransaction::FeesOnly(fees_only_tx) => {
3284                        (vec![], Err(fees_only_tx.load_error), None, None, None)
3285                    }
3286                },
3287                Err(error) => (vec![], Err(error), None, None, None),
3288            };
3289        let logs = logs.unwrap_or_default();
3290
3291        TransactionSimulationResult {
3292            result,
3293            logs,
3294            post_simulation_accounts,
3295            units_consumed,
3296            return_data,
3297            inner_instructions,
3298        }
3299    }
3300
3301    fn get_account_overrides_for_simulation(&self, account_keys: &AccountKeys) -> AccountOverrides {
3302        let mut account_overrides = AccountOverrides::default();
3303        let slot_history_id = sysvar::slot_history::id();
3304        if account_keys.iter().any(|pubkey| *pubkey == slot_history_id) {
3305            let current_account = self.get_account_with_fixed_root(&slot_history_id);
3306            let slot_history = current_account
3307                .as_ref()
3308                .map(|account| from_account::<SlotHistory, _>(account).unwrap())
3309                .unwrap_or_default();
3310            if slot_history.check(self.slot()) == Check::Found {
3311                let ancestors = Ancestors::from(self.proper_ancestors().collect::<Vec<_>>());
3312                if let Some((account, _)) =
3313                    self.load_slow_with_fixed_root(&ancestors, &slot_history_id)
3314                {
3315                    account_overrides.set_slot_history(Some(account));
3316                }
3317            }
3318        }
3319        account_overrides
3320    }
3321
3322    pub fn unlock_accounts<'a, Tx: SVMMessage + 'a>(
3323        &self,
3324        txs_and_results: impl Iterator<Item = (&'a Tx, &'a Result<()>)> + Clone,
3325    ) {
3326        self.rc.accounts.unlock_accounts(txs_and_results)
3327    }
3328
3329    pub fn remove_unrooted_slots(&self, slots: &[(Slot, BankId)]) {
3330        self.rc.accounts.accounts_db.remove_unrooted_slots(slots)
3331    }
3332
3333    pub fn get_hash_age(&self, hash: &Hash) -> Option<u64> {
3334        self.blockhash_queue.read().unwrap().get_hash_age(hash)
3335    }
3336
3337    pub fn is_hash_valid_for_age(&self, hash: &Hash, max_age: usize) -> bool {
3338        self.blockhash_queue
3339            .read()
3340            .unwrap()
3341            .is_hash_valid_for_age(hash, max_age)
3342    }
3343
3344    pub fn collect_balances(
3345        &self,
3346        batch: &TransactionBatch<impl SVMMessage>,
3347    ) -> TransactionBalances {
3348        let mut balances: TransactionBalances = vec![];
3349        for transaction in batch.sanitized_transactions() {
3350            let mut transaction_balances: Vec<u64> = vec![];
3351            for account_key in transaction.account_keys().iter() {
3352                transaction_balances.push(self.get_balance(account_key));
3353            }
3354            balances.push(transaction_balances);
3355        }
3356        balances
3357    }
3358
3359    pub fn load_and_execute_transactions(
3360        &self,
3361        batch: &TransactionBatch<impl TransactionWithMeta>,
3362        max_age: usize,
3363        timings: &mut ExecuteTimings,
3364        error_counters: &mut TransactionErrorMetrics,
3365        processing_config: TransactionProcessingConfig,
3366    ) -> LoadAndExecuteTransactionsOutput {
3367        let sanitized_txs = batch.sanitized_transactions();
3368
3369        let (check_results, check_us) = measure_us!(self.check_transactions(
3370            sanitized_txs,
3371            batch.lock_results(),
3372            max_age,
3373            error_counters,
3374        ));
3375        timings.saturating_add_in_place(ExecuteTimingType::CheckUs, check_us);
3376
3377        let (blockhash, blockhash_lamports_per_signature) =
3378            self.last_blockhash_and_lamports_per_signature();
3379        let rent_collector_with_metrics =
3380            RentCollectorWithMetrics::new(self.rent_collector.clone());
3381        let processing_environment = TransactionProcessingEnvironment {
3382            blockhash,
3383            blockhash_lamports_per_signature,
3384            epoch_total_stake: self.get_current_epoch_total_stake(),
3385            feature_set: Arc::clone(&self.feature_set),
3386            fee_lamports_per_signature: self.fee_structure.lamports_per_signature,
3387            rent_collector: Some(&rent_collector_with_metrics),
3388        };
3389
3390        let sanitized_output = self
3391            .transaction_processor
3392            .load_and_execute_sanitized_transactions(
3393                self,
3394                sanitized_txs,
3395                check_results,
3396                &processing_environment,
3397                &processing_config,
3398            );
3399
3400        // Accumulate the errors returned by the batch processor.
3401        error_counters.accumulate(&sanitized_output.error_metrics);
3402
3403        // Accumulate the transaction batch execution timings.
3404        timings.accumulate(&sanitized_output.execute_timings);
3405
3406        let ((), collect_logs_us) =
3407            measure_us!(self.collect_logs(sanitized_txs, &sanitized_output.processing_results));
3408        timings.saturating_add_in_place(ExecuteTimingType::CollectLogsUs, collect_logs_us);
3409
3410        let mut processed_counts = ProcessedTransactionCounts::default();
3411        let err_count = &mut error_counters.total;
3412
3413        for (processing_result, tx) in sanitized_output
3414            .processing_results
3415            .iter()
3416            .zip(sanitized_txs)
3417        {
3418            if let Some(debug_keys) = &self.transaction_debug_keys {
3419                for key in tx.account_keys().iter() {
3420                    if debug_keys.contains(key) {
3421                        let result = processing_result.flattened_result();
3422                        info!("slot: {} result: {:?} tx: {:?}", self.slot, result, tx);
3423                        break;
3424                    }
3425                }
3426            }
3427
3428            if processing_result.was_processed() {
3429                // Signature count must be accumulated only if the transaction
3430                // is processed, otherwise a mismatched count between banking
3431                // and replay could occur
3432                processed_counts.signature_count +=
3433                    tx.signature_details().num_transaction_signatures();
3434                processed_counts.processed_transactions_count += 1;
3435
3436                if !tx.is_simple_vote_transaction() {
3437                    processed_counts.processed_non_vote_transactions_count += 1;
3438                }
3439            }
3440
3441            match processing_result.flattened_result() {
3442                Ok(()) => {
3443                    processed_counts.processed_with_successful_result_count += 1;
3444                }
3445                Err(err) => {
3446                    if err_count.0 == 0 {
3447                        debug!("tx error: {:?} {:?}", err, tx);
3448                    }
3449                    *err_count += 1;
3450                }
3451            }
3452        }
3453
3454        LoadAndExecuteTransactionsOutput {
3455            processing_results: sanitized_output.processing_results,
3456            processed_counts,
3457        }
3458    }
3459
3460    fn collect_logs(
3461        &self,
3462        transactions: &[impl TransactionWithMeta],
3463        processing_results: &[TransactionProcessingResult],
3464    ) {
3465        let transaction_log_collector_config =
3466            self.transaction_log_collector_config.read().unwrap();
3467        if transaction_log_collector_config.filter == TransactionLogCollectorFilter::None {
3468            return;
3469        }
3470
3471        let collected_logs: Vec<_> = processing_results
3472            .iter()
3473            .zip(transactions)
3474            .filter_map(|(processing_result, transaction)| {
3475                // Skip log collection for unprocessed transactions
3476                let processed_tx = processing_result.processed_transaction()?;
3477                // Skip log collection for unexecuted transactions
3478                let execution_details = processed_tx.execution_details()?;
3479                Self::collect_transaction_logs(
3480                    &transaction_log_collector_config,
3481                    transaction,
3482                    execution_details,
3483                )
3484            })
3485            .collect();
3486
3487        if !collected_logs.is_empty() {
3488            let mut transaction_log_collector = self.transaction_log_collector.write().unwrap();
3489            for (log, filtered_mentioned_addresses) in collected_logs {
3490                let transaction_log_index = transaction_log_collector.logs.len();
3491                transaction_log_collector.logs.push(log);
3492                for key in filtered_mentioned_addresses.into_iter() {
3493                    transaction_log_collector
3494                        .mentioned_address_map
3495                        .entry(key)
3496                        .or_default()
3497                        .push(transaction_log_index);
3498                }
3499            }
3500        }
3501    }
3502
3503    fn collect_transaction_logs(
3504        transaction_log_collector_config: &TransactionLogCollectorConfig,
3505        transaction: &impl TransactionWithMeta,
3506        execution_details: &TransactionExecutionDetails,
3507    ) -> Option<(TransactionLogInfo, Vec<Pubkey>)> {
3508        // Skip log collection if no log messages were recorded
3509        let log_messages = execution_details.log_messages.as_ref()?;
3510
3511        let mut filtered_mentioned_addresses = Vec::new();
3512        if !transaction_log_collector_config
3513            .mentioned_addresses
3514            .is_empty()
3515        {
3516            for key in transaction.account_keys().iter() {
3517                if transaction_log_collector_config
3518                    .mentioned_addresses
3519                    .contains(key)
3520                {
3521                    filtered_mentioned_addresses.push(*key);
3522                }
3523            }
3524        }
3525
3526        let is_vote = transaction.is_simple_vote_transaction();
3527        let store = match transaction_log_collector_config.filter {
3528            TransactionLogCollectorFilter::All => {
3529                !is_vote || !filtered_mentioned_addresses.is_empty()
3530            }
3531            TransactionLogCollectorFilter::AllWithVotes => true,
3532            TransactionLogCollectorFilter::None => false,
3533            TransactionLogCollectorFilter::OnlyMentionedAddresses => {
3534                !filtered_mentioned_addresses.is_empty()
3535            }
3536        };
3537
3538        if store {
3539            Some((
3540                TransactionLogInfo {
3541                    signature: *transaction.signature(),
3542                    result: execution_details.status.clone(),
3543                    is_vote,
3544                    log_messages: log_messages.clone(),
3545                },
3546                filtered_mentioned_addresses,
3547            ))
3548        } else {
3549            None
3550        }
3551    }
3552
3553    /// Load the accounts data size, in bytes
3554    pub fn load_accounts_data_size(&self) -> u64 {
3555        self.accounts_data_size_initial
3556            .saturating_add_signed(self.load_accounts_data_size_delta())
3557    }
3558
3559    /// Load the change in accounts data size in this Bank, in bytes
3560    pub fn load_accounts_data_size_delta(&self) -> i64 {
3561        let delta_on_chain = self.load_accounts_data_size_delta_on_chain();
3562        let delta_off_chain = self.load_accounts_data_size_delta_off_chain();
3563        delta_on_chain.saturating_add(delta_off_chain)
3564    }
3565
3566    /// Load the change in accounts data size in this Bank, in bytes, from on-chain events
3567    /// i.e. transactions
3568    pub fn load_accounts_data_size_delta_on_chain(&self) -> i64 {
3569        self.accounts_data_size_delta_on_chain.load(Acquire)
3570    }
3571
3572    /// Load the change in accounts data size in this Bank, in bytes, from off-chain events
3573    /// i.e. rent collection
3574    pub fn load_accounts_data_size_delta_off_chain(&self) -> i64 {
3575        self.accounts_data_size_delta_off_chain.load(Acquire)
3576    }
3577
3578    /// Update the accounts data size delta from on-chain events by adding `amount`.
3579    /// The arithmetic saturates.
3580    fn update_accounts_data_size_delta_on_chain(&self, amount: i64) {
3581        if amount == 0 {
3582            return;
3583        }
3584
3585        self.accounts_data_size_delta_on_chain
3586            .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_on_chain| {
3587                Some(accounts_data_size_delta_on_chain.saturating_add(amount))
3588            })
3589            // SAFETY: unwrap() is safe since our update fn always returns `Some`
3590            .unwrap();
3591    }
3592
3593    /// Update the accounts data size delta from off-chain events by adding `amount`.
3594    /// The arithmetic saturates.
3595    fn update_accounts_data_size_delta_off_chain(&self, amount: i64) {
3596        if amount == 0 {
3597            return;
3598        }
3599
3600        self.accounts_data_size_delta_off_chain
3601            .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_off_chain| {
3602                Some(accounts_data_size_delta_off_chain.saturating_add(amount))
3603            })
3604            // SAFETY: unwrap() is safe since our update fn always returns `Some`
3605            .unwrap();
3606    }
3607
3608    /// Calculate the data size delta and update the off-chain accounts data size delta
3609    fn calculate_and_update_accounts_data_size_delta_off_chain(
3610        &self,
3611        old_data_size: usize,
3612        new_data_size: usize,
3613    ) {
3614        let data_size_delta = calculate_data_size_delta(old_data_size, new_data_size);
3615        self.update_accounts_data_size_delta_off_chain(data_size_delta);
3616    }
3617
3618    fn filter_program_errors_and_collect_fee(
3619        &self,
3620        processing_results: &[TransactionProcessingResult],
3621    ) {
3622        let mut fees = 0;
3623
3624        processing_results.iter().for_each(|processing_result| {
3625            if let Ok(processed_tx) = processing_result {
3626                fees += processed_tx.fee_details().total_fee();
3627            }
3628        });
3629
3630        self.collector_fees.fetch_add(fees, Relaxed);
3631    }
3632
3633    // Note: this function is not yet used; next PR will call it behind a feature gate
3634    fn filter_program_errors_and_collect_fee_details(
3635        &self,
3636        processing_results: &[TransactionProcessingResult],
3637    ) {
3638        let mut accumulated_fee_details = FeeDetails::default();
3639
3640        processing_results.iter().for_each(|processing_result| {
3641            if let Ok(processed_tx) = processing_result {
3642                accumulated_fee_details.accumulate(&processed_tx.fee_details());
3643            }
3644        });
3645
3646        self.collector_fee_details
3647            .write()
3648            .unwrap()
3649            .accumulate(&accumulated_fee_details);
3650    }
3651
3652    fn update_bank_hash_stats<'a>(&self, accounts: &impl StorableAccounts<'a>) {
3653        let mut stats = BankHashStats::default();
3654        (0..accounts.len()).for_each(|i| {
3655            accounts.account(i, |account| {
3656                stats.update(&account);
3657            })
3658        });
3659        self.bank_hash_stats.accumulate(&stats);
3660    }
3661
3662    pub fn commit_transactions(
3663        &self,
3664        sanitized_txs: &[impl TransactionWithMeta],
3665        processing_results: Vec<TransactionProcessingResult>,
3666        processed_counts: &ProcessedTransactionCounts,
3667        timings: &mut ExecuteTimings,
3668    ) -> Vec<TransactionCommitResult> {
3669        assert!(
3670            !self.freeze_started(),
3671            "commit_transactions() working on a bank that is already frozen or is undergoing freezing!"
3672        );
3673
3674        let ProcessedTransactionCounts {
3675            processed_transactions_count,
3676            processed_non_vote_transactions_count,
3677            processed_with_successful_result_count,
3678            signature_count,
3679        } = *processed_counts;
3680
3681        self.increment_transaction_count(processed_transactions_count);
3682        self.increment_non_vote_transaction_count_since_restart(
3683            processed_non_vote_transactions_count,
3684        );
3685        self.increment_signature_count(signature_count);
3686
3687        let processed_with_failure_result_count =
3688            processed_transactions_count.saturating_sub(processed_with_successful_result_count);
3689        self.transaction_error_count
3690            .fetch_add(processed_with_failure_result_count, Relaxed);
3691
3692        if processed_transactions_count > 0 {
3693            self.is_delta.store(true, Relaxed);
3694            self.transaction_entries_count.fetch_add(1, Relaxed);
3695            self.transactions_per_entry_max
3696                .fetch_max(processed_transactions_count, Relaxed);
3697        }
3698
3699        let ((), store_accounts_us) = measure_us!({
3700            // If geyser is present, we must collect `SanitizedTransaction`
3701            // references in order to comply with that interface - until it
3702            // is changed.
3703            let maybe_transaction_refs = self
3704                .accounts()
3705                .accounts_db
3706                .has_accounts_update_notifier()
3707                .then(|| {
3708                    sanitized_txs
3709                        .iter()
3710                        .map(|tx| tx.as_sanitized_transaction())
3711                        .collect::<Vec<_>>()
3712                });
3713
3714            let (accounts_to_store, transactions) = collect_accounts_to_store(
3715                sanitized_txs,
3716                &maybe_transaction_refs,
3717                &processing_results,
3718            );
3719
3720            let to_store = (self.slot(), accounts_to_store.as_slice());
3721            self.update_bank_hash_stats(&to_store);
3722            self.rc
3723                .accounts
3724                .store_cached(to_store, transactions.as_deref());
3725        });
3726
3727        self.collect_rent(&processing_results);
3728
3729        // Cached vote and stake accounts are synchronized with accounts-db
3730        // after each transaction.
3731        let ((), update_stakes_cache_us) =
3732            measure_us!(self.update_stakes_cache(sanitized_txs, &processing_results));
3733
3734        let ((), update_executors_us) = measure_us!({
3735            let mut cache = None;
3736            for processing_result in &processing_results {
3737                if let Some(ProcessedTransaction::Executed(executed_tx)) =
3738                    processing_result.processed_transaction()
3739                {
3740                    let programs_modified_by_tx = &executed_tx.programs_modified_by_tx;
3741                    if executed_tx.was_successful() && !programs_modified_by_tx.is_empty() {
3742                        cache
3743                            .get_or_insert_with(|| {
3744                                self.transaction_processor.program_cache.write().unwrap()
3745                            })
3746                            .merge(programs_modified_by_tx);
3747                    }
3748                }
3749            }
3750        });
3751
3752        let accounts_data_len_delta = processing_results
3753            .iter()
3754            .filter_map(|processing_result| processing_result.processed_transaction())
3755            .filter_map(|processed_tx| processed_tx.execution_details())
3756            .filter_map(|details| {
3757                details
3758                    .status
3759                    .is_ok()
3760                    .then_some(details.accounts_data_len_delta)
3761            })
3762            .sum();
3763        self.update_accounts_data_size_delta_on_chain(accounts_data_len_delta);
3764
3765        let ((), update_transaction_statuses_us) =
3766            measure_us!(self.update_transaction_statuses(sanitized_txs, &processing_results));
3767
3768        if self.feature_set.is_active(&reward_full_priority_fee::id()) {
3769            self.filter_program_errors_and_collect_fee_details(&processing_results)
3770        } else {
3771            self.filter_program_errors_and_collect_fee(&processing_results)
3772        };
3773
3774        timings.saturating_add_in_place(ExecuteTimingType::StoreUs, store_accounts_us);
3775        timings.saturating_add_in_place(
3776            ExecuteTimingType::UpdateStakesCacheUs,
3777            update_stakes_cache_us,
3778        );
3779        timings.saturating_add_in_place(ExecuteTimingType::UpdateExecutorsUs, update_executors_us);
3780        timings.saturating_add_in_place(
3781            ExecuteTimingType::UpdateTransactionStatuses,
3782            update_transaction_statuses_us,
3783        );
3784
3785        Self::create_commit_results(processing_results)
3786    }
3787
3788    fn create_commit_results(
3789        processing_results: Vec<TransactionProcessingResult>,
3790    ) -> Vec<TransactionCommitResult> {
3791        processing_results
3792            .into_iter()
3793            .map(|processing_result| {
3794                let processing_result = processing_result?;
3795                let executed_units = processing_result.executed_units();
3796                let loaded_accounts_data_size = processing_result.loaded_accounts_data_size();
3797
3798                match processing_result {
3799                    ProcessedTransaction::Executed(executed_tx) => {
3800                        let execution_details = executed_tx.execution_details;
3801                        let LoadedTransaction {
3802                            rent_debits,
3803                            accounts: loaded_accounts,
3804                            fee_details,
3805                            ..
3806                        } = executed_tx.loaded_transaction;
3807
3808                        // Rent is only collected for successfully executed transactions
3809                        let rent_debits = if execution_details.was_successful() {
3810                            rent_debits
3811                        } else {
3812                            RentDebits::default()
3813                        };
3814
3815                        Ok(CommittedTransaction {
3816                            status: execution_details.status,
3817                            log_messages: execution_details.log_messages,
3818                            inner_instructions: execution_details.inner_instructions,
3819                            return_data: execution_details.return_data,
3820                            executed_units,
3821                            fee_details,
3822                            rent_debits,
3823                            loaded_account_stats: TransactionLoadedAccountsStats {
3824                                loaded_accounts_count: loaded_accounts.len(),
3825                                loaded_accounts_data_size,
3826                            },
3827                        })
3828                    }
3829                    ProcessedTransaction::FeesOnly(fees_only_tx) => Ok(CommittedTransaction {
3830                        status: Err(fees_only_tx.load_error),
3831                        log_messages: None,
3832                        inner_instructions: None,
3833                        return_data: None,
3834                        executed_units,
3835                        rent_debits: RentDebits::default(),
3836                        fee_details: fees_only_tx.fee_details,
3837                        loaded_account_stats: TransactionLoadedAccountsStats {
3838                            loaded_accounts_count: fees_only_tx.rollback_accounts.count(),
3839                            loaded_accounts_data_size,
3840                        },
3841                    }),
3842                }
3843            })
3844            .collect()
3845    }
3846
3847    fn collect_rent(&self, processing_results: &[TransactionProcessingResult]) {
3848        let collected_rent = processing_results
3849            .iter()
3850            .filter_map(|processing_result| processing_result.processed_transaction())
3851            .filter_map(|processed_tx| processed_tx.executed_transaction())
3852            .filter(|executed_tx| executed_tx.was_successful())
3853            .map(|executed_tx| executed_tx.loaded_transaction.rent)
3854            .sum();
3855        self.collected_rent.fetch_add(collected_rent, Relaxed);
3856    }
3857
3858    fn run_incinerator(&self) {
3859        if let Some((account, _)) =
3860            self.get_account_modified_since_parent_with_fixed_root(&incinerator::id())
3861        {
3862            self.capitalization.fetch_sub(account.lamports(), Relaxed);
3863            self.store_account(&incinerator::id(), &AccountSharedData::default());
3864        }
3865    }
3866
3867    /// Get stake and stake node accounts
3868    pub(crate) fn get_stake_accounts(&self, minimized_account_set: &DashSet<Pubkey>) {
3869        self.stakes_cache
3870            .stakes()
3871            .stake_delegations()
3872            .iter()
3873            .for_each(|(pubkey, _)| {
3874                minimized_account_set.insert(*pubkey);
3875            });
3876
3877        self.stakes_cache
3878            .stakes()
3879            .staked_nodes()
3880            .par_iter()
3881            .for_each(|(pubkey, _)| {
3882                minimized_account_set.insert(*pubkey);
3883            });
3884    }
3885
3886    /// After deserialize, populate skipped rewrites with accounts that would normally
3887    /// have had their data rewritten in this slot due to rent collection (but didn't).
3888    ///
3889    /// This is required when starting up from a snapshot to verify the bank hash.
3890    ///
3891    /// A second usage is from the `bank_to_xxx_snapshot_archive()` functions.  These fns call
3892    /// `Bank::rehash()` to handle if the user manually modified any accounts and thus requires
3893    /// calculating the bank hash again.  Since calculating the bank hash *takes* the skipped
3894    /// rewrites, this second time will not have any skipped rewrites, and thus the hash would be
3895    /// updated to the wrong value.  So, rebuild the skipped rewrites before rehashing.
3896    fn rebuild_skipped_rewrites(&self) {
3897        // If the feature gate to *not* add rent collection rewrites to the bank hash is enabled,
3898        // then do *not* add anything to our skipped_rewrites.
3899        if self.bank_hash_skips_rent_rewrites() {
3900            return;
3901        }
3902
3903        let (skipped_rewrites, measure_skipped_rewrites) =
3904            measure_time!(self.calculate_skipped_rewrites());
3905        info!(
3906            "Rebuilding skipped rewrites of {} accounts{measure_skipped_rewrites}",
3907            skipped_rewrites.len()
3908        );
3909
3910        *self.skipped_rewrites.lock().unwrap() = skipped_rewrites;
3911    }
3912
3913    /// Calculates (and returns) skipped rewrites for this bank
3914    ///
3915    /// Refer to `rebuild_skipped_rewrites()` for more documentation.
3916    /// This implementation is purposely separate to facilitate testing.
3917    ///
3918    /// The key observation is that accounts in Bank::skipped_rewrites are only used IFF the
3919    /// specific account is *not* already in the accounts delta hash.  If an account is not in
3920    /// the accounts delta hash, then it means the account was not modified.  Since (basically)
3921    /// all accounts are rent exempt, this means (basically) all accounts are unmodified by rent
3922    /// collection.  So we just need to load the accounts that would've been checked for rent
3923    /// collection, hash them, and add them to Bank::skipped_rewrites.
3924    ///
3925    /// As of this writing, there are ~350 million acounts on mainnet-beta.
3926    /// Rent collection almost always collects a single slot at a time.
3927    /// So 1 slot of 432,000, of 350 million accounts, is ~800 accounts per slot.
3928    /// Since we haven't started processing anything yet, it should be fast enough to simply
3929    /// load the accounts directly.
3930    /// Empirically, this takes about 3-4 milliseconds.
3931    fn calculate_skipped_rewrites(&self) -> HashMap<Pubkey, AccountHash> {
3932        // The returned skipped rewrites may include accounts that were actually *not* skipped!
3933        // (This is safe, as per the fn's documentation above.)
3934        self.get_accounts_for_skipped_rewrites()
3935            .map(|(pubkey, account_hash, _account)| (pubkey, account_hash))
3936            .collect()
3937    }
3938
3939    /// Loads accounts that were selected for rent collection this slot.
3940    /// After loading the accounts, also calculate and return the account hashes.
3941    /// This is used when dealing with skipped rewrites.
3942    fn get_accounts_for_skipped_rewrites(
3943        &self,
3944    ) -> impl Iterator<Item = (Pubkey, AccountHash, AccountSharedData)> + '_ {
3945        self.rent_collection_partitions()
3946            .into_iter()
3947            .map(accounts_partition::pubkey_range_from_partition)
3948            .flat_map(|pubkey_range| {
3949                self.rc
3950                    .accounts
3951                    .load_to_collect_rent_eagerly(&self.ancestors, pubkey_range)
3952            })
3953            .map(|(pubkey, account, _slot)| {
3954                let account_hash = AccountsDb::hash_account(&account, &pubkey);
3955                (pubkey, account_hash, account)
3956            })
3957    }
3958
3959    /// Returns the accounts, sorted by pubkey, that were part of accounts delta hash calculation
3960    /// This is used when writing a bank hash details file.
3961    pub(crate) fn get_accounts_for_bank_hash_details(&self) -> Vec<PubkeyHashAccount> {
3962        let accounts_db = &self.rc.accounts.accounts_db;
3963
3964        let mut accounts_written_this_slot =
3965            accounts_db.get_pubkey_hash_account_for_slot(self.slot());
3966
3967        // If we are skipping rewrites but also include them in the accounts delta hash, then we
3968        // need to go load those accounts and add them to the list of accounts written this slot.
3969        if !self.bank_hash_skips_rent_rewrites()
3970            && accounts_db.test_skip_rewrites_but_include_in_bank_hash
3971        {
3972            let pubkeys_written_this_slot: HashSet<_> = accounts_written_this_slot
3973                .iter()
3974                .map(|pubkey_hash_account| pubkey_hash_account.pubkey)
3975                .collect();
3976
3977            let rent_collection_accounts = self.get_accounts_for_skipped_rewrites();
3978            for (pubkey, hash, account) in rent_collection_accounts {
3979                if !pubkeys_written_this_slot.contains(&pubkey) {
3980                    accounts_written_this_slot.push(PubkeyHashAccount {
3981                        pubkey,
3982                        hash,
3983                        account,
3984                    });
3985                }
3986            }
3987        }
3988
3989        // Sort the accounts by pubkey to match the order of the accounts delta hash.
3990        // This also makes comparison of files from different nodes deterministic.
3991        accounts_written_this_slot.sort_unstable_by_key(|account| account.pubkey);
3992        accounts_written_this_slot
3993    }
3994
3995    fn collect_rent_eagerly(&self) {
3996        if self.lazy_rent_collection.load(Relaxed) {
3997            return;
3998        }
3999
4000        let mut measure = Measure::start("collect_rent_eagerly-ms");
4001        let partitions = self.rent_collection_partitions();
4002        let count = partitions.len();
4003        let rent_metrics = RentMetrics::default();
4004        // partitions will usually be 1, but could be more if we skip slots
4005        let mut parallel = count > 1;
4006        if parallel {
4007            let ranges = partitions
4008                .iter()
4009                .map(|partition| {
4010                    (
4011                        *partition,
4012                        accounts_partition::pubkey_range_from_partition(*partition),
4013                    )
4014                })
4015                .collect::<Vec<_>>();
4016            // test every range to make sure ranges are not overlapping
4017            // some tests collect rent from overlapping ranges
4018            // example: [(0, 31, 32), (0, 0, 128), (0, 27, 128)]
4019            // read-modify-write of an account for rent collection cannot be done in parallel
4020            'outer: for i in 0..ranges.len() {
4021                for j in 0..ranges.len() {
4022                    if i == j {
4023                        continue;
4024                    }
4025
4026                    let i = &ranges[i].1;
4027                    let j = &ranges[j].1;
4028                    // make sure i doesn't contain j
4029                    if i.contains(j.start()) || i.contains(j.end()) {
4030                        parallel = false;
4031                        break 'outer;
4032                    }
4033                }
4034            }
4035
4036            if parallel {
4037                let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
4038                thread_pool.install(|| {
4039                    ranges.into_par_iter().for_each(|range| {
4040                        self.collect_rent_in_range(range.0, range.1, &rent_metrics)
4041                    });
4042                });
4043            }
4044        }
4045        if !parallel {
4046            // collect serially
4047            partitions
4048                .into_iter()
4049                .for_each(|partition| self.collect_rent_in_partition(partition, &rent_metrics));
4050        }
4051        measure.stop();
4052        datapoint_info!(
4053            "collect_rent_eagerly",
4054            ("accounts", rent_metrics.count.load(Relaxed), i64),
4055            ("partitions", count, i64),
4056            ("total_time_us", measure.as_us(), i64),
4057            (
4058                "hold_range_us",
4059                rent_metrics.hold_range_us.load(Relaxed),
4060                i64
4061            ),
4062            ("load_us", rent_metrics.load_us.load(Relaxed), i64),
4063            ("collect_us", rent_metrics.collect_us.load(Relaxed), i64),
4064            ("hash_us", rent_metrics.hash_us.load(Relaxed), i64),
4065            ("store_us", rent_metrics.store_us.load(Relaxed), i64),
4066        );
4067    }
4068
4069    fn rent_collection_partitions(&self) -> Vec<Partition> {
4070        if !self.use_fixed_collection_cycle() {
4071            // This mode is for production/development/testing.
4072            // In this mode, we iterate over the whole pubkey value range for each epochs
4073            // including warm-up epochs.
4074            // The only exception is the situation where normal epochs are relatively short
4075            // (currently less than 2 day). In that case, we arrange a single collection
4076            // cycle to be multiple of epochs so that a cycle could be greater than the 2 day.
4077            self.variable_cycle_partitions()
4078        } else {
4079            // This mode is mainly for benchmarking only.
4080            // In this mode, we always iterate over the whole pubkey value range with
4081            // <slot_count_in_two_day> slots as a collection cycle, regardless warm-up or
4082            // alignment between collection cycles and epochs.
4083            // Thus, we can simulate stable processing load of eager rent collection,
4084            // strictly proportional to the number of pubkeys since genesis.
4085            self.fixed_cycle_partitions()
4086        }
4087    }
4088
4089    /// true if rent collection does NOT rewrite accounts whose pubkey indicates
4090    ///  it is time for rent collection, but the account is rent exempt.
4091    /// false if rent collection DOES rewrite accounts if the account is rent exempt
4092    /// This is the default behavior historically.
4093    fn bank_hash_skips_rent_rewrites(&self) -> bool {
4094        self.feature_set
4095            .is_active(&feature_set::skip_rent_rewrites::id())
4096    }
4097
4098    /// true if rent fees should be collected (i.e. disable_rent_fees_collection is NOT enabled)
4099    fn should_collect_rent(&self) -> bool {
4100        !self
4101            .feature_set
4102            .is_active(&feature_set::disable_rent_fees_collection::id())
4103    }
4104
4105    /// Collect rent from `accounts`
4106    ///
4107    /// This fn is called inside a parallel loop from `collect_rent_in_partition()`.  Avoid adding
4108    /// any code that causes contention on shared memory/data (i.e. do not update atomic metrics).
4109    ///
4110    /// The return value is a struct of computed values that `collect_rent_in_partition()` will
4111    /// reduce at the end of its parallel loop.  If possible, place data/computation that cause
4112    /// contention/take locks in the return struct and process them in
4113    /// `collect_rent_from_partition()` after reducing the parallel loop.
4114    fn collect_rent_from_accounts(
4115        &self,
4116        mut accounts: Vec<(Pubkey, AccountSharedData, Slot)>,
4117        rent_paying_pubkeys: Option<&HashSet<Pubkey>>,
4118        partition_index: PartitionIndex,
4119    ) -> CollectRentFromAccountsInfo {
4120        let mut rent_debits = RentDebits::default();
4121        let mut total_rent_collected_info = CollectedInfo::default();
4122        let mut accounts_to_store =
4123            Vec::<(&Pubkey, &AccountSharedData)>::with_capacity(accounts.len());
4124        let mut time_collecting_rent_us = 0;
4125        let mut time_storing_accounts_us = 0;
4126        let can_skip_rewrites = self.bank_hash_skips_rent_rewrites();
4127        let test_skip_rewrites_but_include_in_bank_hash = self
4128            .rc
4129            .accounts
4130            .accounts_db
4131            .test_skip_rewrites_but_include_in_bank_hash;
4132        let mut skipped_rewrites = Vec::default();
4133        for (pubkey, account, _loaded_slot) in accounts.iter_mut() {
4134            let rent_epoch_pre = account.rent_epoch();
4135            let (rent_collected_info, collect_rent_us) = measure_us!(collect_rent_from_account(
4136                &self.feature_set,
4137                &self.rent_collector,
4138                pubkey,
4139                account
4140            ));
4141            time_collecting_rent_us += collect_rent_us;
4142            let rent_epoch_post = account.rent_epoch();
4143
4144            // did the account change in any way due to rent collection?
4145            let rent_epoch_changed = rent_epoch_post != rent_epoch_pre;
4146            let account_changed = rent_collected_info.rent_amount != 0 || rent_epoch_changed;
4147
4148            // always store the account, regardless if it changed or not
4149            let always_store_accounts =
4150                !can_skip_rewrites && !test_skip_rewrites_but_include_in_bank_hash;
4151
4152            // only store accounts where we collected rent
4153            // but get the hash for all these accounts even if collected rent is 0 (= not updated).
4154            // Also, there's another subtle side-effect from rewrites: this
4155            // ensures we verify the whole on-chain state (= all accounts)
4156            // via the bank delta hash slowly once per an epoch.
4157            if account_changed || always_store_accounts {
4158                if rent_collected_info.rent_amount > 0 {
4159                    if let Some(rent_paying_pubkeys) = rent_paying_pubkeys {
4160                        if !rent_paying_pubkeys.contains(pubkey) {
4161                            let partition_from_pubkey = accounts_partition::partition_from_pubkey(
4162                                pubkey,
4163                                self.epoch_schedule.slots_per_epoch,
4164                            );
4165                            // Submit datapoint instead of assert while we verify this is correct
4166                            datapoint_warn!(
4167                                "bank-unexpected_rent_paying_pubkey",
4168                                ("slot", self.slot(), i64),
4169                                ("pubkey", pubkey.to_string(), String),
4170                                ("partition_index", partition_index, i64),
4171                                ("partition_from_pubkey", partition_from_pubkey, i64)
4172                            );
4173                            warn!(
4174                                "Collecting rent from unexpected pubkey: {}, slot: {}, parent_slot: {:?}, \
4175                                partition_index: {}, partition_from_pubkey: {}",
4176                                pubkey,
4177                                self.slot(),
4178                                self.parent().map(|bank| bank.slot()),
4179                                partition_index,
4180                                partition_from_pubkey,
4181                            );
4182                        }
4183                    }
4184                } else {
4185                    debug_assert_eq!(rent_collected_info.rent_amount, 0);
4186                    if rent_epoch_changed {
4187                        datapoint_info!(
4188                            "bank-rent_collection_updated_only_rent_epoch",
4189                            ("slot", self.slot(), i64),
4190                            ("pubkey", pubkey.to_string(), String),
4191                            ("rent_epoch_pre", rent_epoch_pre, i64),
4192                            ("rent_epoch_post", rent_epoch_post, i64),
4193                        );
4194                    }
4195                }
4196                total_rent_collected_info += rent_collected_info;
4197                accounts_to_store.push((pubkey, account));
4198            } else if !account_changed
4199                && !can_skip_rewrites
4200                && test_skip_rewrites_but_include_in_bank_hash
4201            {
4202                // include rewrites that we skipped in the accounts delta hash.
4203                // This is what consensus requires prior to activation of bank_hash_skips_rent_rewrites.
4204                // This code path exists to allow us to test the long term effects on validators when the skipped rewrites
4205                // feature is enabled.
4206                let hash = AccountsDb::hash_account(account, pubkey);
4207                skipped_rewrites.push((*pubkey, hash));
4208            }
4209            rent_debits.insert(pubkey, rent_collected_info.rent_amount, account.lamports());
4210        }
4211
4212        if !accounts_to_store.is_empty() {
4213            // TODO: Maybe do not call `store_accounts()` here.  Instead return `accounts_to_store`
4214            // and have `collect_rent_in_partition()` perform all the stores.
4215            let (_, store_accounts_us) =
4216                measure_us!(self.store_accounts((self.slot(), &accounts_to_store[..])));
4217            time_storing_accounts_us += store_accounts_us;
4218        }
4219
4220        CollectRentFromAccountsInfo {
4221            skipped_rewrites,
4222            rent_collected_info: total_rent_collected_info,
4223            rent_rewards: rent_debits.into_unordered_rewards_iter().collect(),
4224            time_collecting_rent_us,
4225            time_storing_accounts_us,
4226            num_accounts: accounts.len(),
4227        }
4228    }
4229
4230    /// convert 'partition' to a pubkey range and 'collect_rent_in_range'
4231    fn collect_rent_in_partition(&self, partition: Partition, metrics: &RentMetrics) {
4232        let subrange_full = accounts_partition::pubkey_range_from_partition(partition);
4233        self.collect_rent_in_range(partition, subrange_full, metrics)
4234    }
4235
4236    /// 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)
4237    fn get_rent_paying_pubkeys(&self, partition: &Partition) -> Option<HashSet<Pubkey>> {
4238        self.rc
4239            .accounts
4240            .accounts_db
4241            .accounts_index
4242            .rent_paying_accounts_by_partition
4243            .get()
4244            .and_then(|rent_paying_accounts| {
4245                rent_paying_accounts.is_initialized().then(|| {
4246                    accounts_partition::get_partition_end_indexes(partition)
4247                        .into_iter()
4248                        .flat_map(|end_index| {
4249                            rent_paying_accounts.get_pubkeys_in_partition_index(end_index)
4250                        })
4251                        .cloned()
4252                        .collect::<HashSet<_>>()
4253                })
4254            })
4255    }
4256
4257    /// load accounts with pubkeys in 'subrange_full'
4258    /// collect rent and update 'account.rent_epoch' as necessary
4259    /// store accounts, whether rent was collected or not (depending on whether we skipping rewrites is enabled)
4260    /// update bank's rewrites set for all rewrites that were skipped
4261    fn collect_rent_in_range(
4262        &self,
4263        partition: Partition,
4264        subrange_full: RangeInclusive<Pubkey>,
4265        metrics: &RentMetrics,
4266    ) {
4267        let mut hold_range = Measure::start("hold_range");
4268        let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
4269        thread_pool.install(|| {
4270            self.rc
4271                .accounts
4272                .hold_range_in_memory(&subrange_full, true, thread_pool);
4273            hold_range.stop();
4274            metrics.hold_range_us.fetch_add(hold_range.as_us(), Relaxed);
4275
4276            let rent_paying_pubkeys_ = self.get_rent_paying_pubkeys(&partition);
4277            let rent_paying_pubkeys = rent_paying_pubkeys_.as_ref();
4278
4279            // divide the range into num_threads smaller ranges and process in parallel
4280            // Note that 'pubkey_range_from_partition' cannot easily be re-used here to break the range smaller.
4281            // It has special handling of 0..0 and partition_count changes affect all ranges unevenly.
4282            let num_threads = solana_accounts_db::accounts_db::quarter_thread_count() as u64;
4283            let sz = std::mem::size_of::<u64>();
4284            let start_prefix = accounts_partition::prefix_from_pubkey(subrange_full.start());
4285            let end_prefix_inclusive = accounts_partition::prefix_from_pubkey(subrange_full.end());
4286            let range = end_prefix_inclusive - start_prefix;
4287            let increment = range / num_threads;
4288            let mut results = (0..num_threads)
4289                .into_par_iter()
4290                .map(|chunk| {
4291                    let offset = |chunk| start_prefix + chunk * increment;
4292                    let start = offset(chunk);
4293                    let last = chunk == num_threads - 1;
4294                    let merge_prefix = |prefix: u64, mut bound: Pubkey| {
4295                        bound.as_mut()[0..sz].copy_from_slice(&prefix.to_be_bytes());
4296                        bound
4297                    };
4298                    let start = merge_prefix(start, *subrange_full.start());
4299                    let (accounts, measure_load_accounts) = measure_time!(if last {
4300                        let end = *subrange_full.end();
4301                        let subrange = start..=end; // IN-clusive
4302                        self.rc
4303                            .accounts
4304                            .load_to_collect_rent_eagerly(&self.ancestors, subrange)
4305                    } else {
4306                        let end = merge_prefix(offset(chunk + 1), *subrange_full.start());
4307                        let subrange = start..end; // EX-clusive, the next 'start' will be this same value
4308                        self.rc
4309                            .accounts
4310                            .load_to_collect_rent_eagerly(&self.ancestors, subrange)
4311                    });
4312                    CollectRentInPartitionInfo::new(
4313                        self.collect_rent_from_accounts(accounts, rent_paying_pubkeys, partition.1),
4314                        Duration::from_nanos(measure_load_accounts.as_ns()),
4315                    )
4316                })
4317                .reduce(
4318                    CollectRentInPartitionInfo::default,
4319                    CollectRentInPartitionInfo::reduce,
4320                );
4321
4322            self.skipped_rewrites
4323                .lock()
4324                .unwrap()
4325                .extend(results.skipped_rewrites);
4326
4327            // We cannot assert here that we collected from all expected keys.
4328            // Some accounts may have been topped off or may have had all funds removed and gone to 0 lamports.
4329
4330            self.rc
4331                .accounts
4332                .hold_range_in_memory(&subrange_full, false, thread_pool);
4333
4334            self.collected_rent
4335                .fetch_add(results.rent_collected, Relaxed);
4336            self.update_accounts_data_size_delta_off_chain(
4337                -(results.accounts_data_size_reclaimed as i64),
4338            );
4339            self.rewards
4340                .write()
4341                .unwrap()
4342                .append(&mut results.rent_rewards);
4343
4344            metrics
4345                .load_us
4346                .fetch_add(results.time_loading_accounts_us, Relaxed);
4347            metrics
4348                .collect_us
4349                .fetch_add(results.time_collecting_rent_us, Relaxed);
4350            metrics
4351                .store_us
4352                .fetch_add(results.time_storing_accounts_us, Relaxed);
4353            metrics.count.fetch_add(results.num_accounts, Relaxed);
4354        });
4355    }
4356
4357    pub(crate) fn fixed_cycle_partitions_between_slots(
4358        &self,
4359        starting_slot: Slot,
4360        ending_slot: Slot,
4361    ) -> Vec<Partition> {
4362        let slot_count_in_two_day = self.slot_count_in_two_day();
4363        accounts_partition::get_partitions(ending_slot, starting_slot, slot_count_in_two_day)
4364    }
4365
4366    fn fixed_cycle_partitions(&self) -> Vec<Partition> {
4367        self.fixed_cycle_partitions_between_slots(self.parent_slot(), self.slot())
4368    }
4369
4370    pub(crate) fn variable_cycle_partitions_between_slots(
4371        &self,
4372        starting_slot: Slot,
4373        ending_slot: Slot,
4374    ) -> Vec<Partition> {
4375        let (starting_epoch, mut starting_slot_index) =
4376            self.get_epoch_and_slot_index(starting_slot);
4377        let (ending_epoch, ending_slot_index) = self.get_epoch_and_slot_index(ending_slot);
4378
4379        let mut partitions = vec![];
4380        if starting_epoch < ending_epoch {
4381            let slot_skipped = (ending_slot - starting_slot) > 1;
4382            if slot_skipped {
4383                // Generate special partitions because there are skipped slots
4384                // exactly at the epoch transition.
4385
4386                let parent_last_slot_index = self.get_slots_in_epoch(starting_epoch) - 1;
4387
4388                // ... for parent epoch
4389                partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
4390                    starting_slot_index,
4391                    parent_last_slot_index,
4392                    starting_epoch,
4393                ));
4394
4395                if ending_slot_index > 0 {
4396                    // ... for current epoch
4397                    partitions.push(self.partition_from_slot_indexes_with_gapped_epochs(
4398                        0,
4399                        0,
4400                        ending_epoch,
4401                    ));
4402                }
4403            }
4404            starting_slot_index = 0;
4405        }
4406
4407        partitions.push(self.partition_from_normal_slot_indexes(
4408            starting_slot_index,
4409            ending_slot_index,
4410            ending_epoch,
4411        ));
4412
4413        partitions
4414    }
4415
4416    fn variable_cycle_partitions(&self) -> Vec<Partition> {
4417        self.variable_cycle_partitions_between_slots(self.parent_slot(), self.slot())
4418    }
4419
4420    fn do_partition_from_slot_indexes(
4421        &self,
4422        start_slot_index: SlotIndex,
4423        end_slot_index: SlotIndex,
4424        epoch: Epoch,
4425        generated_for_gapped_epochs: bool,
4426    ) -> Partition {
4427        let slot_count_per_epoch = self.get_slots_in_epoch(epoch);
4428
4429        let cycle_params = if !self.use_multi_epoch_collection_cycle(epoch) {
4430            // mnb should always go through this code path
4431            accounts_partition::rent_single_epoch_collection_cycle_params(
4432                epoch,
4433                slot_count_per_epoch,
4434            )
4435        } else {
4436            accounts_partition::rent_multi_epoch_collection_cycle_params(
4437                epoch,
4438                slot_count_per_epoch,
4439                self.first_normal_epoch(),
4440                self.slot_count_in_two_day() / slot_count_per_epoch,
4441            )
4442        };
4443        accounts_partition::get_partition_from_slot_indexes(
4444            cycle_params,
4445            start_slot_index,
4446            end_slot_index,
4447            generated_for_gapped_epochs,
4448        )
4449    }
4450
4451    fn partition_from_normal_slot_indexes(
4452        &self,
4453        start_slot_index: SlotIndex,
4454        end_slot_index: SlotIndex,
4455        epoch: Epoch,
4456    ) -> Partition {
4457        self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, false)
4458    }
4459
4460    fn partition_from_slot_indexes_with_gapped_epochs(
4461        &self,
4462        start_slot_index: SlotIndex,
4463        end_slot_index: SlotIndex,
4464        epoch: Epoch,
4465    ) -> Partition {
4466        self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, true)
4467    }
4468
4469    // Given short epochs, it's too costly to collect rent eagerly
4470    // within an epoch, so lower the frequency of it.
4471    // These logic isn't strictly eager anymore and should only be used
4472    // for development/performance purpose.
4473    // Absolutely not under ClusterType::MainnetBeta!!!!
4474    fn use_multi_epoch_collection_cycle(&self, epoch: Epoch) -> bool {
4475        // Force normal behavior, disabling multi epoch collection cycle for manual local testing
4476        #[cfg(not(test))]
4477        if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
4478        {
4479            return false;
4480        }
4481
4482        epoch >= self.first_normal_epoch()
4483            && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
4484    }
4485
4486    pub(crate) fn use_fixed_collection_cycle(&self) -> bool {
4487        // Force normal behavior, disabling fixed collection cycle for manual local testing
4488        #[cfg(not(test))]
4489        if self.slot_count_per_normal_epoch() == solana_sdk::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH
4490        {
4491            return false;
4492        }
4493
4494        self.cluster_type() != ClusterType::MainnetBeta
4495            && self.slot_count_per_normal_epoch() < self.slot_count_in_two_day()
4496    }
4497
4498    fn slot_count_in_two_day(&self) -> SlotCount {
4499        Self::slot_count_in_two_day_helper(self.ticks_per_slot)
4500    }
4501
4502    // This value is specially chosen to align with slots per epoch in mainnet-beta and testnet
4503    // Also, assume 500GB account data set as the extreme, then for 2 day (=48 hours) to collect
4504    // rent eagerly, we'll consume 5.7 MB/s IO bandwidth, bidirectionally.
4505    pub fn slot_count_in_two_day_helper(ticks_per_slot: SlotCount) -> SlotCount {
4506        2 * DEFAULT_TICKS_PER_SECOND * SECONDS_PER_DAY / ticks_per_slot
4507    }
4508
4509    fn slot_count_per_normal_epoch(&self) -> SlotCount {
4510        self.get_slots_in_epoch(self.first_normal_epoch())
4511    }
4512
4513    pub fn cluster_type(&self) -> ClusterType {
4514        // unwrap is safe; self.cluster_type is ensured to be Some() always...
4515        // we only using Option here for ABI compatibility...
4516        self.cluster_type.unwrap()
4517    }
4518
4519    /// Process a batch of transactions.
4520    #[must_use]
4521    pub fn load_execute_and_commit_transactions(
4522        &self,
4523        batch: &TransactionBatch<impl TransactionWithMeta>,
4524        max_age: usize,
4525        collect_balances: bool,
4526        recording_config: ExecutionRecordingConfig,
4527        timings: &mut ExecuteTimings,
4528        log_messages_bytes_limit: Option<usize>,
4529    ) -> (Vec<TransactionCommitResult>, TransactionBalancesSet) {
4530        self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4531            batch,
4532            max_age,
4533            collect_balances,
4534            recording_config,
4535            timings,
4536            log_messages_bytes_limit,
4537            None::<fn(&mut _, &_) -> _>,
4538        )
4539        .unwrap()
4540    }
4541
4542    pub fn load_execute_and_commit_transactions_with_pre_commit_callback<'a>(
4543        &'a self,
4544        batch: &TransactionBatch<impl TransactionWithMeta>,
4545        max_age: usize,
4546        collect_balances: bool,
4547        recording_config: ExecutionRecordingConfig,
4548        timings: &mut ExecuteTimings,
4549        log_messages_bytes_limit: Option<usize>,
4550        pre_commit_callback: impl FnOnce(
4551            &mut ExecuteTimings,
4552            &[TransactionProcessingResult],
4553        ) -> PreCommitResult<'a>,
4554    ) -> Result<(Vec<TransactionCommitResult>, TransactionBalancesSet)> {
4555        self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4556            batch,
4557            max_age,
4558            collect_balances,
4559            recording_config,
4560            timings,
4561            log_messages_bytes_limit,
4562            Some(pre_commit_callback),
4563        )
4564    }
4565
4566    fn do_load_execute_and_commit_transactions_with_pre_commit_callback<'a>(
4567        &'a self,
4568        batch: &TransactionBatch<impl TransactionWithMeta>,
4569        max_age: usize,
4570        collect_balances: bool,
4571        recording_config: ExecutionRecordingConfig,
4572        timings: &mut ExecuteTimings,
4573        log_messages_bytes_limit: Option<usize>,
4574        pre_commit_callback: Option<
4575            impl FnOnce(&mut ExecuteTimings, &[TransactionProcessingResult]) -> PreCommitResult<'a>,
4576        >,
4577    ) -> Result<(Vec<TransactionCommitResult>, TransactionBalancesSet)> {
4578        let pre_balances = if collect_balances {
4579            self.collect_balances(batch)
4580        } else {
4581            vec![]
4582        };
4583
4584        let LoadAndExecuteTransactionsOutput {
4585            processing_results,
4586            processed_counts,
4587        } = self.load_and_execute_transactions(
4588            batch,
4589            max_age,
4590            timings,
4591            &mut TransactionErrorMetrics::default(),
4592            TransactionProcessingConfig {
4593                account_overrides: None,
4594                check_program_modification_slot: self.check_program_modification_slot,
4595                compute_budget: self.compute_budget(),
4596                log_messages_bytes_limit,
4597                limit_to_load_programs: false,
4598                recording_config,
4599                transaction_account_lock_limit: Some(self.get_transaction_account_lock_limit()),
4600            },
4601        );
4602
4603        // pre_commit_callback could initiate an atomic operation (i.e. poh recording with block
4604        // producing unified scheduler). in that case, it returns Some(freeze_lock), which should
4605        // unlocked only after calling commit_transactions() immediately after calling the
4606        // callback.
4607        let freeze_lock = if let Some(pre_commit_callback) = pre_commit_callback {
4608            pre_commit_callback(timings, &processing_results)?
4609        } else {
4610            None
4611        };
4612        let commit_results = self.commit_transactions(
4613            batch.sanitized_transactions(),
4614            processing_results,
4615            &processed_counts,
4616            timings,
4617        );
4618        drop(freeze_lock);
4619        let post_balances = if collect_balances {
4620            self.collect_balances(batch)
4621        } else {
4622            vec![]
4623        };
4624        Ok((
4625            commit_results,
4626            TransactionBalancesSet::new(pre_balances, post_balances),
4627        ))
4628    }
4629
4630    /// Process a Transaction. This is used for unit tests and simply calls the vector
4631    /// Bank::process_transactions method.
4632    pub fn process_transaction(&self, tx: &Transaction) -> Result<()> {
4633        self.try_process_transactions(std::iter::once(tx))?[0].clone()?;
4634        tx.signatures
4635            .first()
4636            .map_or(Ok(()), |sig| self.get_signature_status(sig).unwrap())
4637    }
4638
4639    /// Process a Transaction and store metadata. This is used for tests and the banks services. It
4640    /// replicates the vector Bank::process_transaction method with metadata recording enabled.
4641    pub fn process_transaction_with_metadata(
4642        &self,
4643        tx: impl Into<VersionedTransaction>,
4644    ) -> Result<CommittedTransaction> {
4645        let txs = vec![tx.into()];
4646        let batch = self.prepare_entry_batch(txs)?;
4647
4648        let (mut commit_results, ..) = self.load_execute_and_commit_transactions(
4649            &batch,
4650            MAX_PROCESSING_AGE,
4651            false, // collect_balances
4652            ExecutionRecordingConfig {
4653                enable_cpi_recording: false,
4654                enable_log_recording: true,
4655                enable_return_data_recording: true,
4656            },
4657            &mut ExecuteTimings::default(),
4658            Some(1000 * 1000),
4659        );
4660
4661        commit_results.remove(0)
4662    }
4663
4664    /// Process multiple transaction in a single batch. This is used for benches and unit tests.
4665    /// Short circuits if any of the transactions do not pass sanitization checks.
4666    pub fn try_process_transactions<'a>(
4667        &self,
4668        txs: impl Iterator<Item = &'a Transaction>,
4669    ) -> Result<Vec<Result<()>>> {
4670        let txs = txs
4671            .map(|tx| VersionedTransaction::from(tx.clone()))
4672            .collect();
4673        self.try_process_entry_transactions(txs)
4674    }
4675
4676    /// Process multiple transaction in a single batch. This is used for benches and unit tests.
4677    /// Short circuits if any of the transactions do not pass sanitization checks.
4678    pub fn try_process_entry_transactions(
4679        &self,
4680        txs: Vec<VersionedTransaction>,
4681    ) -> Result<Vec<Result<()>>> {
4682        let batch = self.prepare_entry_batch(txs)?;
4683        Ok(self.process_transaction_batch(&batch))
4684    }
4685
4686    #[must_use]
4687    fn process_transaction_batch(
4688        &self,
4689        batch: &TransactionBatch<impl TransactionWithMeta>,
4690    ) -> Vec<Result<()>> {
4691        self.load_execute_and_commit_transactions(
4692            batch,
4693            MAX_PROCESSING_AGE,
4694            false,
4695            ExecutionRecordingConfig::new_single_setting(false),
4696            &mut ExecuteTimings::default(),
4697            None,
4698        )
4699        .0
4700        .into_iter()
4701        .map(|commit_result| commit_result.map(|_| ()))
4702        .collect()
4703    }
4704
4705    /// Create, sign, and process a Transaction from `keypair` to `to` of
4706    /// `n` lamports where `blockhash` is the last Entry ID observed by the client.
4707    pub fn transfer(&self, n: u64, keypair: &Keypair, to: &Pubkey) -> Result<Signature> {
4708        let blockhash = self.last_blockhash();
4709        let tx = system_transaction::transfer(keypair, to, n, blockhash);
4710        let signature = tx.signatures[0];
4711        self.process_transaction(&tx).map(|_| signature)
4712    }
4713
4714    pub fn read_balance(account: &AccountSharedData) -> u64 {
4715        account.lamports()
4716    }
4717    /// Each program would need to be able to introspect its own state
4718    /// this is hard-coded to the Budget language
4719    pub fn get_balance(&self, pubkey: &Pubkey) -> u64 {
4720        self.get_account(pubkey)
4721            .map(|x| Self::read_balance(&x))
4722            .unwrap_or(0)
4723    }
4724
4725    /// Compute all the parents of the bank in order
4726    pub fn parents(&self) -> Vec<Arc<Bank>> {
4727        let mut parents = vec![];
4728        let mut bank = self.parent();
4729        while let Some(parent) = bank {
4730            parents.push(parent.clone());
4731            bank = parent.parent();
4732        }
4733        parents
4734    }
4735
4736    /// Compute all the parents of the bank including this bank itself
4737    pub fn parents_inclusive(self: Arc<Self>) -> Vec<Arc<Bank>> {
4738        let mut parents = self.parents();
4739        parents.insert(0, self);
4740        parents
4741    }
4742
4743    /// fn store the single `account` with `pubkey`.
4744    /// Uses `store_accounts`, which works on a vector of accounts.
4745    pub fn store_account(&self, pubkey: &Pubkey, account: &AccountSharedData) {
4746        self.store_accounts((self.slot(), &[(pubkey, account)][..]))
4747    }
4748
4749    pub fn store_accounts<'a>(&self, accounts: impl StorableAccounts<'a>) {
4750        assert!(!self.freeze_started());
4751        let mut m = Measure::start("stakes_cache.check_and_store");
4752        let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
4753
4754        (0..accounts.len()).for_each(|i| {
4755            accounts.account(i, |account| {
4756                self.stakes_cache.check_and_store(
4757                    account.pubkey(),
4758                    &account,
4759                    new_warmup_cooldown_rate_epoch,
4760                )
4761            })
4762        });
4763        self.update_bank_hash_stats(&accounts);
4764        self.rc.accounts.store_accounts_cached(accounts);
4765        m.stop();
4766        self.rc
4767            .accounts
4768            .accounts_db
4769            .stats
4770            .stakes_cache_check_and_store_us
4771            .fetch_add(m.as_us(), Relaxed);
4772    }
4773
4774    pub fn force_flush_accounts_cache(&self) {
4775        self.rc
4776            .accounts
4777            .accounts_db
4778            .flush_accounts_cache(true, Some(self.slot()))
4779    }
4780
4781    pub fn flush_accounts_cache_if_needed(&self) {
4782        self.rc
4783            .accounts
4784            .accounts_db
4785            .flush_accounts_cache(false, Some(self.slot()))
4786    }
4787
4788    /// Technically this issues (or even burns!) new lamports,
4789    /// so be extra careful for its usage
4790    fn store_account_and_update_capitalization(
4791        &self,
4792        pubkey: &Pubkey,
4793        new_account: &AccountSharedData,
4794    ) {
4795        let old_account_data_size =
4796            if let Some(old_account) = self.get_account_with_fixed_root_no_cache(pubkey) {
4797                match new_account.lamports().cmp(&old_account.lamports()) {
4798                    std::cmp::Ordering::Greater => {
4799                        let increased = new_account.lamports() - old_account.lamports();
4800                        trace!(
4801                            "store_account_and_update_capitalization: increased: {} {}",
4802                            pubkey,
4803                            increased
4804                        );
4805                        self.capitalization.fetch_add(increased, Relaxed);
4806                    }
4807                    std::cmp::Ordering::Less => {
4808                        let decreased = old_account.lamports() - new_account.lamports();
4809                        trace!(
4810                            "store_account_and_update_capitalization: decreased: {} {}",
4811                            pubkey,
4812                            decreased
4813                        );
4814                        self.capitalization.fetch_sub(decreased, Relaxed);
4815                    }
4816                    std::cmp::Ordering::Equal => {}
4817                }
4818                old_account.data().len()
4819            } else {
4820                trace!(
4821                    "store_account_and_update_capitalization: created: {} {}",
4822                    pubkey,
4823                    new_account.lamports()
4824                );
4825                self.capitalization
4826                    .fetch_add(new_account.lamports(), Relaxed);
4827                0
4828            };
4829
4830        self.store_account(pubkey, new_account);
4831        self.calculate_and_update_accounts_data_size_delta_off_chain(
4832            old_account_data_size,
4833            new_account.data().len(),
4834        );
4835    }
4836
4837    pub fn accounts(&self) -> Arc<Accounts> {
4838        self.rc.accounts.clone()
4839    }
4840
4841    fn finish_init(
4842        &mut self,
4843        genesis_config: &GenesisConfig,
4844        additional_builtins: Option<&[BuiltinPrototype]>,
4845        debug_do_not_add_builtins: bool,
4846    ) {
4847        self.rewards_pool_pubkeys =
4848            Arc::new(genesis_config.rewards_pools.keys().cloned().collect());
4849
4850        self.apply_feature_activations(
4851            ApplyFeatureActivationsCaller::FinishInit,
4852            debug_do_not_add_builtins,
4853        );
4854
4855        // Cost-Tracker is not serialized in snapshot or any configs.
4856        // We must apply previously activated features related to limits here
4857        // so that the initial bank state is consistent with the feature set.
4858        // Cost-tracker limits are propagated through children banks.
4859        if self
4860            .feature_set
4861            .is_active(&feature_set::raise_block_limits_to_50m::id())
4862        {
4863            let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits();
4864            self.write_cost_tracker().unwrap().set_limits(
4865                account_cost_limit,
4866                block_cost_limit,
4867                vote_cost_limit,
4868            );
4869        }
4870
4871        if !debug_do_not_add_builtins {
4872            for builtin in BUILTINS
4873                .iter()
4874                .chain(additional_builtins.unwrap_or(&[]).iter())
4875            {
4876                // The builtin should be added if it has no enable feature ID
4877                // and it has not been migrated to Core BPF.
4878                //
4879                // If a program was previously migrated to Core BPF, accountsDB
4880                // from snapshot should contain the BPF program accounts.
4881                let builtin_is_bpf = |program_id: &Pubkey| {
4882                    self.get_account(program_id)
4883                        .map(|a| a.owner() == &bpf_loader_upgradeable::id())
4884                        .unwrap_or(false)
4885                };
4886                if builtin.enable_feature_id.is_none() && !builtin_is_bpf(&builtin.program_id) {
4887                    self.transaction_processor.add_builtin(
4888                        self,
4889                        builtin.program_id,
4890                        builtin.name,
4891                        ProgramCacheEntry::new_builtin(0, builtin.name.len(), builtin.entrypoint),
4892                    );
4893                }
4894            }
4895            for precompile in get_precompiles() {
4896                if precompile.feature.is_none() {
4897                    self.add_precompile(&precompile.program_id);
4898                }
4899            }
4900        }
4901
4902        self.transaction_processor
4903            .configure_program_runtime_environments(
4904                Some(Arc::new(
4905                    create_program_runtime_environment_v1(
4906                        &self.feature_set,
4907                        &self.compute_budget().unwrap_or_default(),
4908                        false, /* deployment */
4909                        false, /* debugging_features */
4910                    )
4911                    .unwrap(),
4912                )),
4913                Some(Arc::new(create_program_runtime_environment_v2(
4914                    &self.compute_budget().unwrap_or_default(),
4915                    false, /* debugging_features */
4916                ))),
4917            );
4918    }
4919
4920    pub fn set_inflation(&self, inflation: Inflation) {
4921        *self.inflation.write().unwrap() = inflation;
4922    }
4923
4924    /// Get a snapshot of the current set of hard forks
4925    pub fn hard_forks(&self) -> HardForks {
4926        self.hard_forks.read().unwrap().clone()
4927    }
4928
4929    pub fn register_hard_fork(&self, new_hard_fork_slot: Slot) {
4930        let bank_slot = self.slot();
4931
4932        let lock = self.freeze_lock();
4933        let bank_frozen = *lock != Hash::default();
4934        if new_hard_fork_slot < bank_slot {
4935            warn!(
4936                "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is older \
4937                than the bank at slot {bank_slot} that attempted to register it."
4938            );
4939        } else if (new_hard_fork_slot == bank_slot) && bank_frozen {
4940            warn!(
4941                "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is the same \
4942                slot as the bank at slot {bank_slot} that attempted to register it, but that \
4943                bank is already frozen."
4944            );
4945        } else {
4946            self.hard_forks
4947                .write()
4948                .unwrap()
4949                .register(new_hard_fork_slot);
4950        }
4951    }
4952
4953    pub fn get_account_with_fixed_root_no_cache(
4954        &self,
4955        pubkey: &Pubkey,
4956    ) -> Option<AccountSharedData> {
4957        self.load_account_with(pubkey, |_| false)
4958            .map(|(acc, _slot)| acc)
4959    }
4960
4961    fn load_account_with(
4962        &self,
4963        pubkey: &Pubkey,
4964        callback: impl for<'local> Fn(&'local AccountSharedData) -> bool,
4965    ) -> Option<(AccountSharedData, Slot)> {
4966        self.rc
4967            .accounts
4968            .accounts_db
4969            .load_account_with(&self.ancestors, pubkey, callback)
4970    }
4971
4972    // Hi! leaky abstraction here....
4973    // try to use get_account_with_fixed_root() if it's called ONLY from on-chain runtime account
4974    // processing. That alternative fn provides more safety.
4975    pub fn get_account(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
4976        self.get_account_modified_slot(pubkey)
4977            .map(|(acc, _slot)| acc)
4978    }
4979
4980    // Hi! leaky abstraction here....
4981    // use this over get_account() if it's called ONLY from on-chain runtime account
4982    // processing (i.e. from in-band replay/banking stage; that ensures root is *fixed* while
4983    // running).
4984    // pro: safer assertion can be enabled inside AccountsDb
4985    // con: panics!() if called from off-chain processing
4986    pub fn get_account_with_fixed_root(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
4987        self.get_account_modified_slot_with_fixed_root(pubkey)
4988            .map(|(acc, _slot)| acc)
4989    }
4990
4991    // See note above get_account_with_fixed_root() about when to prefer this function
4992    pub fn get_account_modified_slot_with_fixed_root(
4993        &self,
4994        pubkey: &Pubkey,
4995    ) -> Option<(AccountSharedData, Slot)> {
4996        self.load_slow_with_fixed_root(&self.ancestors, pubkey)
4997    }
4998
4999    pub fn get_account_modified_slot(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
5000        self.load_slow(&self.ancestors, pubkey)
5001    }
5002
5003    fn load_slow(
5004        &self,
5005        ancestors: &Ancestors,
5006        pubkey: &Pubkey,
5007    ) -> Option<(AccountSharedData, Slot)> {
5008        // get_account (= primary this fn caller) may be called from on-chain Bank code even if we
5009        // try hard to use get_account_with_fixed_root for that purpose...
5010        // so pass safer LoadHint:Unspecified here as a fallback
5011        self.rc.accounts.load_without_fixed_root(ancestors, pubkey)
5012    }
5013
5014    fn load_slow_with_fixed_root(
5015        &self,
5016        ancestors: &Ancestors,
5017        pubkey: &Pubkey,
5018    ) -> Option<(AccountSharedData, Slot)> {
5019        self.rc.accounts.load_with_fixed_root(ancestors, pubkey)
5020    }
5021
5022    pub fn get_program_accounts(
5023        &self,
5024        program_id: &Pubkey,
5025        config: &ScanConfig,
5026    ) -> ScanResult<Vec<TransactionAccount>> {
5027        self.rc
5028            .accounts
5029            .load_by_program(&self.ancestors, self.bank_id, program_id, config)
5030    }
5031
5032    pub fn get_filtered_program_accounts<F: Fn(&AccountSharedData) -> bool>(
5033        &self,
5034        program_id: &Pubkey,
5035        filter: F,
5036        config: &ScanConfig,
5037    ) -> ScanResult<Vec<TransactionAccount>> {
5038        self.rc.accounts.load_by_program_with_filter(
5039            &self.ancestors,
5040            self.bank_id,
5041            program_id,
5042            filter,
5043            config,
5044        )
5045    }
5046
5047    pub fn get_filtered_indexed_accounts<F: Fn(&AccountSharedData) -> bool>(
5048        &self,
5049        index_key: &IndexKey,
5050        filter: F,
5051        config: &ScanConfig,
5052        byte_limit_for_scan: Option<usize>,
5053    ) -> ScanResult<Vec<TransactionAccount>> {
5054        self.rc.accounts.load_by_index_key_with_filter(
5055            &self.ancestors,
5056            self.bank_id,
5057            index_key,
5058            filter,
5059            config,
5060            byte_limit_for_scan,
5061        )
5062    }
5063
5064    pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
5065        self.rc.accounts.account_indexes_include_key(key)
5066    }
5067
5068    /// Returns all the accounts this bank can load
5069    pub fn get_all_accounts(&self, sort_results: bool) -> ScanResult<Vec<PubkeyAccountSlot>> {
5070        self.rc
5071            .accounts
5072            .load_all(&self.ancestors, self.bank_id, sort_results)
5073    }
5074
5075    // Scans all the accounts this bank can load, applying `scan_func`
5076    pub fn scan_all_accounts<F>(&self, scan_func: F, sort_results: bool) -> ScanResult<()>
5077    where
5078        F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>),
5079    {
5080        self.rc
5081            .accounts
5082            .scan_all(&self.ancestors, self.bank_id, scan_func, sort_results)
5083    }
5084
5085    pub fn get_program_accounts_modified_since_parent(
5086        &self,
5087        program_id: &Pubkey,
5088    ) -> Vec<TransactionAccount> {
5089        self.rc
5090            .accounts
5091            .load_by_program_slot(self.slot(), Some(program_id))
5092    }
5093
5094    pub fn get_transaction_logs(
5095        &self,
5096        address: Option<&Pubkey>,
5097    ) -> Option<Vec<TransactionLogInfo>> {
5098        self.transaction_log_collector
5099            .read()
5100            .unwrap()
5101            .get_logs_for_address(address)
5102    }
5103
5104    /// Returns all the accounts stored in this slot
5105    pub fn get_all_accounts_modified_since_parent(&self) -> Vec<TransactionAccount> {
5106        self.rc.accounts.load_by_program_slot(self.slot(), None)
5107    }
5108
5109    // if you want get_account_modified_since_parent without fixed_root, please define so...
5110    fn get_account_modified_since_parent_with_fixed_root(
5111        &self,
5112        pubkey: &Pubkey,
5113    ) -> Option<(AccountSharedData, Slot)> {
5114        let just_self: Ancestors = Ancestors::from(vec![self.slot()]);
5115        if let Some((account, slot)) = self.load_slow_with_fixed_root(&just_self, pubkey) {
5116            if slot == self.slot() {
5117                return Some((account, slot));
5118            }
5119        }
5120        None
5121    }
5122
5123    pub fn get_largest_accounts(
5124        &self,
5125        num: usize,
5126        filter_by_address: &HashSet<Pubkey>,
5127        filter: AccountAddressFilter,
5128        sort_results: bool,
5129    ) -> ScanResult<Vec<(Pubkey, u64)>> {
5130        self.rc.accounts.load_largest_accounts(
5131            &self.ancestors,
5132            self.bank_id,
5133            num,
5134            filter_by_address,
5135            filter,
5136            sort_results,
5137        )
5138    }
5139
5140    /// Return the accumulated executed transaction count
5141    pub fn transaction_count(&self) -> u64 {
5142        self.transaction_count.load(Relaxed)
5143    }
5144
5145    /// Returns the number of non-vote transactions processed without error
5146    /// since the most recent boot from snapshot or genesis.
5147    /// This value is not shared though the network, nor retained
5148    /// within snapshots, but is preserved in `Bank::new_from_parent`.
5149    pub fn non_vote_transaction_count_since_restart(&self) -> u64 {
5150        self.non_vote_transaction_count_since_restart.load(Relaxed)
5151    }
5152
5153    /// Return the transaction count executed only in this bank
5154    pub fn executed_transaction_count(&self) -> u64 {
5155        self.transaction_count()
5156            .saturating_sub(self.parent().map_or(0, |parent| parent.transaction_count()))
5157    }
5158
5159    pub fn transaction_error_count(&self) -> u64 {
5160        self.transaction_error_count.load(Relaxed)
5161    }
5162
5163    pub fn transaction_entries_count(&self) -> u64 {
5164        self.transaction_entries_count.load(Relaxed)
5165    }
5166
5167    pub fn transactions_per_entry_max(&self) -> u64 {
5168        self.transactions_per_entry_max.load(Relaxed)
5169    }
5170
5171    fn increment_transaction_count(&self, tx_count: u64) {
5172        self.transaction_count.fetch_add(tx_count, Relaxed);
5173    }
5174
5175    fn increment_non_vote_transaction_count_since_restart(&self, tx_count: u64) {
5176        self.non_vote_transaction_count_since_restart
5177            .fetch_add(tx_count, Relaxed);
5178    }
5179
5180    pub fn signature_count(&self) -> u64 {
5181        self.signature_count.load(Relaxed)
5182    }
5183
5184    fn increment_signature_count(&self, signature_count: u64) {
5185        self.signature_count.fetch_add(signature_count, Relaxed);
5186    }
5187
5188    pub fn get_signature_status_processed_since_parent(
5189        &self,
5190        signature: &Signature,
5191    ) -> Option<Result<()>> {
5192        if let Some((slot, status)) = self.get_signature_status_slot(signature) {
5193            if slot <= self.slot() {
5194                return Some(status);
5195            }
5196        }
5197        None
5198    }
5199
5200    pub fn get_signature_status_with_blockhash(
5201        &self,
5202        signature: &Signature,
5203        blockhash: &Hash,
5204    ) -> Option<Result<()>> {
5205        let rcache = self.status_cache.read().unwrap();
5206        rcache
5207            .get_status(signature, blockhash, &self.ancestors)
5208            .map(|v| v.1)
5209    }
5210
5211    pub fn get_signature_status_slot(&self, signature: &Signature) -> Option<(Slot, Result<()>)> {
5212        let rcache = self.status_cache.read().unwrap();
5213        rcache.get_status_any_blockhash(signature, &self.ancestors)
5214    }
5215
5216    pub fn get_signature_status(&self, signature: &Signature) -> Option<Result<()>> {
5217        self.get_signature_status_slot(signature).map(|v| v.1)
5218    }
5219
5220    pub fn has_signature(&self, signature: &Signature) -> bool {
5221        self.get_signature_status_slot(signature).is_some()
5222    }
5223
5224    /// Hash the `accounts` HashMap. This represents a validator's interpretation
5225    ///  of the delta of the ledger since the last vote and up to now
5226    fn hash_internal_state(&self) -> Hash {
5227        let measure_total = Measure::start("");
5228        let slot = self.slot();
5229
5230        let delta_hash_info = (!self
5231            .feature_set
5232            .is_active(&feature_set::remove_accounts_delta_hash::id()))
5233        .then(|| {
5234            measure_us!({
5235                self.rc
5236                    .accounts
5237                    .accounts_db
5238                    .calculate_accounts_delta_hash_internal(
5239                        slot,
5240                        None,
5241                        self.skipped_rewrites.lock().unwrap().clone(),
5242                    )
5243            })
5244        });
5245
5246        let mut hash = if let Some((accounts_delta_hash, _measure)) = delta_hash_info.as_ref() {
5247            hashv(&[
5248                self.parent_hash.as_ref(),
5249                accounts_delta_hash.0.as_ref(),
5250                &self.signature_count().to_le_bytes(),
5251                self.last_blockhash().as_ref(),
5252            ])
5253        } else {
5254            hashv(&[
5255                self.parent_hash.as_ref(),
5256                &self.signature_count().to_le_bytes(),
5257                self.last_blockhash().as_ref(),
5258            ])
5259        };
5260
5261        let accounts_hash_info = if self
5262            .feature_set
5263            .is_active(&feature_set::accounts_lt_hash::id())
5264        {
5265            let accounts_lt_hash = &*self.accounts_lt_hash.lock().unwrap();
5266            let lt_hash_bytes = bytemuck::must_cast_slice(&accounts_lt_hash.0 .0);
5267            hash = hashv(&[hash.as_ref(), lt_hash_bytes]);
5268            let checksum = accounts_lt_hash.0.checksum();
5269            Some(format!(", accounts_lt_hash checksum: {checksum}"))
5270        } else {
5271            let epoch_accounts_hash = self.wait_get_epoch_accounts_hash();
5272            epoch_accounts_hash.map(|epoch_accounts_hash| {
5273                hash = hashv(&[hash.as_ref(), epoch_accounts_hash.as_ref().as_ref()]);
5274                format!(", epoch_accounts_hash: {:?}", epoch_accounts_hash.as_ref())
5275            })
5276        };
5277
5278        let buf = self
5279            .hard_forks
5280            .read()
5281            .unwrap()
5282            .get_hash_data(slot, self.parent_slot());
5283        if let Some(buf) = buf {
5284            let hard_forked_hash = extend_and_hash(&hash, &buf);
5285            warn!("hard fork at slot {slot} by hashing {buf:?}: {hash} => {hard_forked_hash}");
5286            hash = hard_forked_hash;
5287        }
5288
5289        #[cfg(feature = "dev-context-only-utils")]
5290        let hash_override = self
5291            .hash_overrides
5292            .lock()
5293            .unwrap()
5294            .get_bank_hash_override(slot)
5295            .copied()
5296            .inspect(|&hash_override| {
5297                if hash_override != hash {
5298                    info!(
5299                        "bank: slot: {}: overrode bank hash: {} with {}",
5300                        self.slot(),
5301                        hash,
5302                        hash_override
5303                    );
5304                }
5305            });
5306        // Avoid to optimize out `hash` along with the whole computation by super smart rustc.
5307        // hash_override is used by ledger-tool's simulate-block-production, which prefers
5308        // the actual bank freezing processing for accurate simulation.
5309        #[cfg(feature = "dev-context-only-utils")]
5310        let hash = hash_override.unwrap_or(std::hint::black_box(hash));
5311
5312        let bank_hash_stats = self.bank_hash_stats.load();
5313
5314        let total_us = measure_total.end_as_us();
5315
5316        let (accounts_delta_hash_us, accounts_delta_hash_log) = delta_hash_info
5317            .map(|(hash, us)| (us, format!(" accounts_delta: {}", hash.0)))
5318            .unzip();
5319        datapoint_info!(
5320            "bank-hash_internal_state",
5321            ("slot", slot, i64),
5322            ("total_us", total_us, i64),
5323            ("accounts_delta_hash_us", accounts_delta_hash_us, Option<i64>),
5324        );
5325        info!(
5326            "bank frozen: {slot} hash: {hash}{} signature_count: {} last_blockhash: {} capitalization: {}{}, stats: {bank_hash_stats:?}",
5327            accounts_delta_hash_log.unwrap_or_default(),
5328            self.signature_count(),
5329            self.last_blockhash(),
5330            self.capitalization(),
5331            accounts_hash_info.unwrap_or_default(),
5332        );
5333        hash
5334    }
5335
5336    pub fn collector_fees(&self) -> u64 {
5337        self.collector_fees.load(Relaxed)
5338    }
5339
5340    /// The epoch accounts hash is hashed into the bank's hash once per epoch at a predefined slot.
5341    /// Should it be included in *this* bank?
5342    fn should_include_epoch_accounts_hash(&self) -> bool {
5343        if !epoch_accounts_hash_utils::is_enabled_this_epoch(self) {
5344            return false;
5345        }
5346
5347        let stop_slot = epoch_accounts_hash_utils::calculation_stop(self);
5348        self.parent_slot() < stop_slot && self.slot() >= stop_slot
5349    }
5350
5351    /// If the epoch accounts hash should be included in this Bank, then fetch it. If the EAH
5352    /// calculation has not completed yet, this fn will block until it does complete.
5353    fn wait_get_epoch_accounts_hash(&self) -> Option<EpochAccountsHash> {
5354        if !self.should_include_epoch_accounts_hash() {
5355            return None;
5356        }
5357
5358        let (epoch_accounts_hash, waiting_time_us) = measure_us!(self
5359            .rc
5360            .accounts
5361            .accounts_db
5362            .epoch_accounts_hash_manager
5363            .wait_get_epoch_accounts_hash());
5364
5365        datapoint_info!(
5366            "bank-wait_get_epoch_accounts_hash",
5367            ("slot", self.slot(), i64),
5368            ("waiting-time-us", waiting_time_us, i64),
5369        );
5370        Some(epoch_accounts_hash)
5371    }
5372
5373    /// Used by ledger tool to run a final hash calculation once all ledger replay has completed.
5374    /// This should not be called by validator code.
5375    pub fn run_final_hash_calc(&self, on_halt_store_hash_raw_data_for_debug: bool) {
5376        self.force_flush_accounts_cache();
5377        // note that this slot may not be a root
5378        _ = self.verify_accounts_hash(
5379            None,
5380            VerifyAccountsHashConfig {
5381                test_hash_calculation: false,
5382                ignore_mismatch: true,
5383                require_rooted_bank: false,
5384                run_in_background: false,
5385                store_hash_raw_data_for_debug: on_halt_store_hash_raw_data_for_debug,
5386            },
5387            None,
5388        );
5389    }
5390
5391    /// Recalculate the accounts hash from the account stores. Used to verify a snapshot.
5392    /// return true if all is good
5393    /// Only called from startup or test code.
5394    #[must_use]
5395    fn verify_accounts_hash(
5396        &self,
5397        base: Option<(Slot, /*capitalization*/ u64)>,
5398        mut config: VerifyAccountsHashConfig,
5399        duplicates_lt_hash: Option<Box<DuplicatesLtHash>>,
5400    ) -> bool {
5401        #[derive(Debug, Eq, PartialEq)]
5402        enum VerifyKind {
5403            Merkle,
5404            Lattice,
5405        }
5406
5407        let accounts = &self.rc.accounts;
5408        // Wait until initial hash calc is complete before starting a new hash calc.
5409        // This should only occur when we halt at a slot in ledger-tool.
5410        accounts
5411            .accounts_db
5412            .verify_accounts_hash_in_bg
5413            .join_background_thread();
5414
5415        let slot = self.slot();
5416
5417        let verify_kind = match (
5418            duplicates_lt_hash.is_some(),
5419            self.rc
5420                .accounts
5421                .accounts_db
5422                .is_experimental_accumulator_hash_enabled(),
5423        ) {
5424            (true, _) => VerifyKind::Lattice,
5425            (false, false) => VerifyKind::Merkle,
5426            (false, true) => {
5427                // Calculating the accounts lt hash from storages *requires* a duplicates_lt_hash.
5428                // If it is None here, then we must use the index instead, which also means we
5429                // cannot run in the background.
5430                config.run_in_background = false;
5431                VerifyKind::Lattice
5432            }
5433        };
5434
5435        if config.require_rooted_bank && !accounts.accounts_db.accounts_index.is_alive_root(slot) {
5436            if let Some(parent) = self.parent() {
5437                info!(
5438                    "slot {slot} is not a root, so verify accounts hash on parent bank at slot {}",
5439                    parent.slot(),
5440                );
5441                if verify_kind == VerifyKind::Lattice {
5442                    // The duplicates_lt_hash is only valid for the current slot, so we must fall
5443                    // back to verifying the accounts lt hash with the index (which also means we
5444                    // cannot run in the background).
5445                    config.run_in_background = false;
5446                }
5447                return parent.verify_accounts_hash(base, config, None);
5448            } else {
5449                // this will result in mismatch errors
5450                // accounts hash calc doesn't include unrooted slots
5451                panic!("cannot verify accounts hash because slot {slot} is not a root");
5452            }
5453        }
5454
5455        // The snapshot storages must be captured *before* starting the background verification.
5456        // Otherwise, it is possible that a delayed call to `get_snapshot_storages()` will *not*
5457        // get the correct storages required to calculate and verify the accounts hashes.
5458        let snapshot_storages = self.rc.accounts.accounts_db.get_storages(RangeFull);
5459        let capitalization = self.capitalization();
5460        let verify_config = VerifyAccountsHashAndLamportsConfig {
5461            ancestors: &self.ancestors,
5462            epoch_schedule: self.epoch_schedule(),
5463            rent_collector: self.rent_collector(),
5464            test_hash_calculation: config.test_hash_calculation,
5465            ignore_mismatch: config.ignore_mismatch,
5466            store_detailed_debug_info: config.store_hash_raw_data_for_debug,
5467            use_bg_thread_pool: config.run_in_background,
5468        };
5469
5470        info!(
5471            "Verifying accounts, in background? {}, verify kind: {verify_kind:?}",
5472            config.run_in_background,
5473        );
5474        if config.run_in_background {
5475            let accounts = Arc::clone(accounts);
5476            let accounts_ = Arc::clone(&accounts);
5477            let ancestors = self.ancestors.clone();
5478            let epoch_schedule = self.epoch_schedule().clone();
5479            let rent_collector = self.rent_collector().clone();
5480            let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5481            accounts.accounts_db.verify_accounts_hash_in_bg.start(|| {
5482                Builder::new()
5483                    .name("solBgHashVerify".into())
5484                    .spawn(move || {
5485                        info!("Initial background accounts hash verification has started");
5486                        let start = Instant::now();
5487                        let mut lattice_verify_time = None;
5488                        let mut merkle_verify_time = None;
5489                        let is_ok = match verify_kind {
5490                            VerifyKind::Lattice => {
5491                                // accounts lt hash is *enabled* so use lattice-based verification
5492                                let accounts_db = &accounts_.accounts_db;
5493                                let (calculated_accounts_lt_hash, duration) =
5494                                    meas_dur!(accounts_db.thread_pool_hash.install(|| {
5495                                        accounts_db
5496                                            .calculate_accounts_lt_hash_at_startup_from_storages(
5497                                                snapshot_storages.0.as_slice(),
5498                                                &duplicates_lt_hash.unwrap(),
5499                                            )
5500                                    }));
5501                                let is_ok =
5502                                    calculated_accounts_lt_hash == expected_accounts_lt_hash;
5503                                if !is_ok {
5504                                    let expected = expected_accounts_lt_hash.0.checksum();
5505                                    let calculated = calculated_accounts_lt_hash.0.checksum();
5506                                    error!(
5507                                        "Verifying accounts failed: accounts lattice hashes do not \
5508                                         match, expected: {expected}, calculated: {calculated}",
5509                                    );
5510                                }
5511                                lattice_verify_time = Some(duration);
5512                                is_ok
5513                            }
5514                            VerifyKind::Merkle => {
5515                                // accounts lt hash is *disabled* so use merkle-based verification
5516                                let snapshot_storages_and_slots = (
5517                                    snapshot_storages.0.as_slice(),
5518                                    snapshot_storages.1.as_slice(),
5519                                );
5520                                let (is_ok, duration) = meas_dur!(accounts_
5521                                    .verify_accounts_hash_and_lamports(
5522                                        snapshot_storages_and_slots,
5523                                        slot,
5524                                        capitalization,
5525                                        base,
5526                                        VerifyAccountsHashAndLamportsConfig {
5527                                            ancestors: &ancestors,
5528                                            epoch_schedule: &epoch_schedule,
5529                                            rent_collector: &rent_collector,
5530                                            ..verify_config
5531                                        },
5532                                    ));
5533                                merkle_verify_time = Some(duration);
5534                                is_ok
5535                            }
5536                        };
5537                        accounts_
5538                            .accounts_db
5539                            .verify_accounts_hash_in_bg
5540                            .background_finished();
5541                        let total_time = start.elapsed();
5542                        datapoint_info!(
5543                            "startup_verify_accounts",
5544                            ("total_us", total_time.as_micros(), i64),
5545                            (
5546                                "verify_accounts_lt_hash_us",
5547                                lattice_verify_time.as_ref().map(Duration::as_micros),
5548                                Option<i64>
5549                            ),
5550                            ("verify_accounts_hash_us",
5551                                merkle_verify_time.as_ref().map(Duration::as_micros),
5552                                Option<i64>
5553                            ),
5554                        );
5555                        info!("Initial background accounts hash verification has stopped");
5556                        is_ok
5557                    })
5558                    .unwrap()
5559            });
5560            true // initial result is true. We haven't failed yet. If verification fails, we'll panic from bg thread.
5561        } else {
5562            match verify_kind {
5563                VerifyKind::Lattice => {
5564                    let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5565                    let calculated_accounts_lt_hash = if let Some(duplicates_lt_hash) =
5566                        duplicates_lt_hash
5567                    {
5568                        accounts
5569                            .accounts_db
5570                            .calculate_accounts_lt_hash_at_startup_from_storages(
5571                                snapshot_storages.0.as_slice(),
5572                                &duplicates_lt_hash,
5573                            )
5574                    } else {
5575                        accounts
5576                            .accounts_db
5577                            .calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors, slot)
5578                    };
5579                    let is_ok = calculated_accounts_lt_hash == expected_accounts_lt_hash;
5580                    if !is_ok {
5581                        let expected = expected_accounts_lt_hash.0.checksum();
5582                        let calculated = calculated_accounts_lt_hash.0.checksum();
5583                        error!(
5584                            "Verifying accounts failed: accounts lattice hashes do not \
5585                             match, expected: {expected}, calculated: {calculated}",
5586                        );
5587                    }
5588                    is_ok
5589                }
5590                VerifyKind::Merkle => {
5591                    let snapshot_storages_and_slots = (
5592                        snapshot_storages.0.as_slice(),
5593                        snapshot_storages.1.as_slice(),
5594                    );
5595                    let is_ok = accounts.verify_accounts_hash_and_lamports(
5596                        snapshot_storages_and_slots,
5597                        slot,
5598                        capitalization,
5599                        base,
5600                        verify_config,
5601                    );
5602                    self.set_initial_accounts_hash_verification_completed();
5603                    is_ok
5604                }
5605            }
5606        }
5607    }
5608
5609    /// Specify that initial verification has completed.
5610    /// Called internally when verification runs in the foreground thread.
5611    /// Also has to be called by some tests which don't do verification on startup.
5612    pub fn set_initial_accounts_hash_verification_completed(&self) {
5613        self.rc
5614            .accounts
5615            .accounts_db
5616            .verify_accounts_hash_in_bg
5617            .verification_complete();
5618    }
5619
5620    /// return true if bg hash verification is complete
5621    /// return false if bg hash verification has not completed yet
5622    /// if hash verification failed, a panic will occur
5623    pub fn has_initial_accounts_hash_verification_completed(&self) -> bool {
5624        self.rc
5625            .accounts
5626            .accounts_db
5627            .verify_accounts_hash_in_bg
5628            .check_complete()
5629    }
5630
5631    /// Get this bank's storages to use for snapshots.
5632    ///
5633    /// If a base slot is provided, return only the storages that are *higher* than this slot.
5634    pub fn get_snapshot_storages(&self, base_slot: Option<Slot>) -> Vec<Arc<AccountStorageEntry>> {
5635        // if a base slot is provided, request storages starting at the slot *after*
5636        let start_slot = base_slot.map_or(0, |slot| slot.saturating_add(1));
5637        // we want to *include* the storage at our slot
5638        let requested_slots = start_slot..=self.slot();
5639
5640        self.rc.accounts.accounts_db.get_storages(requested_slots).0
5641    }
5642
5643    #[must_use]
5644    fn verify_hash(&self) -> bool {
5645        assert!(self.is_frozen());
5646        let calculated_hash = self.hash_internal_state();
5647        let expected_hash = self.hash();
5648
5649        if calculated_hash == expected_hash {
5650            true
5651        } else {
5652            warn!(
5653                "verify failed: slot: {}, {} (calculated) != {} (expected)",
5654                self.slot(),
5655                calculated_hash,
5656                expected_hash
5657            );
5658            false
5659        }
5660    }
5661
5662    pub fn verify_transaction(
5663        &self,
5664        tx: VersionedTransaction,
5665        verification_mode: TransactionVerificationMode,
5666    ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5667        let sanitized_tx = {
5668            let size =
5669                bincode::serialized_size(&tx).map_err(|_| TransactionError::SanitizeFailure)?;
5670            if size > PACKET_DATA_SIZE as u64 {
5671                return Err(TransactionError::SanitizeFailure);
5672            }
5673            let message_hash = if verification_mode == TransactionVerificationMode::FullVerification
5674            {
5675                tx.verify_and_hash_message()?
5676            } else {
5677                tx.message.hash()
5678            };
5679
5680            RuntimeTransaction::try_create(
5681                tx,
5682                MessageHash::Precomputed(message_hash),
5683                None,
5684                self,
5685                self.get_reserved_account_keys(),
5686            )
5687        }?;
5688
5689        let move_precompile_verification_to_svm = self
5690            .feature_set
5691            .is_active(&feature_set::move_precompile_verification_to_svm::id());
5692        if !move_precompile_verification_to_svm && {
5693            verification_mode == TransactionVerificationMode::HashAndVerifyPrecompiles
5694                || verification_mode == TransactionVerificationMode::FullVerification
5695        } {
5696            verify_precompiles(&sanitized_tx, &self.feature_set)?;
5697        }
5698
5699        Ok(sanitized_tx)
5700    }
5701
5702    pub fn fully_verify_transaction(
5703        &self,
5704        tx: VersionedTransaction,
5705    ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5706        self.verify_transaction(tx, TransactionVerificationMode::FullVerification)
5707    }
5708
5709    /// Checks if the transaction violates the bank's reserved keys.
5710    /// This needs to be checked upon epoch boundary crosses because the
5711    /// reserved key set may have changed since the initial sanitization.
5712    pub fn check_reserved_keys(&self, tx: &impl SVMMessage) -> Result<()> {
5713        // Check keys against the reserved set - these failures simply require us
5714        // to re-sanitize the transaction. We do not need to drop the transaction.
5715        let reserved_keys = self.get_reserved_account_keys();
5716        for (index, key) in tx.account_keys().iter().enumerate() {
5717            if tx.is_writable(index) && reserved_keys.contains(key) {
5718                return Err(TransactionError::ResanitizationNeeded);
5719            }
5720        }
5721
5722        Ok(())
5723    }
5724
5725    /// only called from ledger-tool or tests
5726    fn calculate_capitalization(&self, debug_verify: bool) -> u64 {
5727        let is_startup = true;
5728        self.rc
5729            .accounts
5730            .accounts_db
5731            .verify_accounts_hash_in_bg
5732            .join_background_thread();
5733        self.rc
5734            .accounts
5735            .accounts_db
5736            .update_accounts_hash_with_verify_from(
5737                // we have to use the index since the slot could be in the write cache still
5738                CalcAccountsHashDataSource::IndexForTests,
5739                debug_verify,
5740                self.slot(),
5741                &self.ancestors,
5742                None,
5743                self.epoch_schedule(),
5744                &self.rent_collector,
5745                is_startup,
5746            )
5747            .1
5748    }
5749
5750    /// only called from tests or ledger tool
5751    pub fn calculate_and_verify_capitalization(&self, debug_verify: bool) -> bool {
5752        let calculated = self.calculate_capitalization(debug_verify);
5753        let expected = self.capitalization();
5754        if calculated == expected {
5755            true
5756        } else {
5757            warn!(
5758                "Capitalization mismatch: calculated: {} != expected: {}",
5759                calculated, expected
5760            );
5761            false
5762        }
5763    }
5764
5765    /// Forcibly overwrites current capitalization by actually recalculating accounts' balances.
5766    /// This should only be used for developing purposes.
5767    pub fn set_capitalization(&self) -> u64 {
5768        let old = self.capitalization();
5769        // We cannot debug verify the hash calculation here because calculate_capitalization will use the index calculation due to callers using the write cache.
5770        // debug_verify only exists as an extra debugging step under the assumption that this code path is only used for tests. But, this is used by ledger-tool create-snapshot
5771        // for example.
5772        let debug_verify = false;
5773        self.capitalization
5774            .store(self.calculate_capitalization(debug_verify), Relaxed);
5775        old
5776    }
5777
5778    /// Returns the `AccountsHash` that was calculated for this bank's slot
5779    ///
5780    /// This fn is used when creating a snapshot with ledger-tool, or when
5781    /// packaging a snapshot into an archive (used to get the `SnapshotHash`).
5782    pub fn get_accounts_hash(&self) -> Option<AccountsHash> {
5783        self.rc
5784            .accounts
5785            .accounts_db
5786            .get_accounts_hash(self.slot())
5787            .map(|(accounts_hash, _)| accounts_hash)
5788    }
5789
5790    /// Returns the `IncrementalAccountsHash` that was calculated for this bank's slot
5791    ///
5792    /// This fn is used when creating an incremental snapshot with ledger-tool, or when
5793    /// packaging a snapshot into an archive (used to get the `SnapshotHash`).
5794    pub fn get_incremental_accounts_hash(&self) -> Option<IncrementalAccountsHash> {
5795        self.rc
5796            .accounts
5797            .accounts_db
5798            .get_incremental_accounts_hash(self.slot())
5799            .map(|(incremental_accounts_hash, _)| incremental_accounts_hash)
5800    }
5801
5802    /// Returns the `SnapshotHash` for this bank's slot
5803    ///
5804    /// This fn is used at startup to verify the bank was rebuilt correctly.
5805    ///
5806    /// # Panics
5807    ///
5808    /// If the snapshots lt hash feature is not enabled, panics if there is both-or-neither of an
5809    /// `AccountsHash` and an `IncrementalAccountsHash` for this bank's slot.  There may only be
5810    /// one or the other.
5811    pub fn get_snapshot_hash(&self) -> SnapshotHash {
5812        if self.is_snapshots_lt_hash_enabled() {
5813            self.get_lattice_snapshot_hash()
5814        } else {
5815            self.get_merkle_snapshot_hash()
5816        }
5817    }
5818
5819    /// Returns the merkle-based `SnapshotHash` for this bank's slot
5820    ///
5821    /// This fn is used at startup to verify the bank was rebuilt correctly.
5822    ///
5823    /// # Panics
5824    ///
5825    /// If the snapshots lt hash feature is not enabled, panics if there is both-or-neither of an
5826    /// `AccountsHash` and an `IncrementalAccountsHash` for this bank's slot.  There may only be
5827    /// one or the other.
5828    pub fn get_merkle_snapshot_hash(&self) -> SnapshotHash {
5829        let accounts_hash = self.get_accounts_hash();
5830        let incremental_accounts_hash = self.get_incremental_accounts_hash();
5831        let accounts_hash_kind = match (accounts_hash, incremental_accounts_hash) {
5832            (Some(_), Some(_)) => panic!("Both full and incremental accounts hashes are present for slot {}; it is ambiguous which one to use for the snapshot hash!", self.slot()),
5833            (Some(accounts_hash), None) => accounts_hash.into(),
5834            (None, Some(incremental_accounts_hash)) => incremental_accounts_hash.into(),
5835            (None, None) => panic!("accounts hash is required to get snapshot hash"),
5836        };
5837        let epoch_accounts_hash = self.get_epoch_accounts_hash_to_serialize();
5838        SnapshotHash::new(
5839            &MerkleOrLatticeAccountsHash::Merkle(accounts_hash_kind),
5840            epoch_accounts_hash.as_ref(),
5841            None,
5842        )
5843    }
5844
5845    /// Returns the lattice-based `SnapshotHash` for this bank's slot
5846    ///
5847    /// This fn is used at startup to verify the bank was rebuilt correctly.
5848    pub fn get_lattice_snapshot_hash(&self) -> SnapshotHash {
5849        SnapshotHash::new(
5850            &MerkleOrLatticeAccountsHash::Lattice,
5851            None,
5852            Some(self.accounts_lt_hash.lock().unwrap().0.checksum()),
5853        )
5854    }
5855
5856    pub fn load_account_into_read_cache(&self, key: &Pubkey) {
5857        self.rc
5858            .accounts
5859            .accounts_db
5860            .load_account_into_read_cache(&self.ancestors, key);
5861    }
5862
5863    pub fn update_accounts_hash(
5864        &self,
5865        data_source: CalcAccountsHashDataSource,
5866        mut debug_verify: bool,
5867        is_startup: bool,
5868    ) -> AccountsHash {
5869        let (accounts_hash, total_lamports) = self
5870            .rc
5871            .accounts
5872            .accounts_db
5873            .update_accounts_hash_with_verify_from(
5874                data_source,
5875                debug_verify,
5876                self.slot(),
5877                &self.ancestors,
5878                Some(self.capitalization()),
5879                self.epoch_schedule(),
5880                &self.rent_collector,
5881                is_startup,
5882            );
5883        if total_lamports != self.capitalization() {
5884            datapoint_info!(
5885                "capitalization_mismatch",
5886                ("slot", self.slot(), i64),
5887                ("calculated_lamports", total_lamports, i64),
5888                ("capitalization", self.capitalization(), i64),
5889            );
5890
5891            if !debug_verify {
5892                // cap mismatch detected. It has been logged to metrics above.
5893                // Run both versions of the calculation to attempt to get more info.
5894                debug_verify = true;
5895                self.rc
5896                    .accounts
5897                    .accounts_db
5898                    .update_accounts_hash_with_verify_from(
5899                        data_source,
5900                        debug_verify,
5901                        self.slot(),
5902                        &self.ancestors,
5903                        Some(self.capitalization()),
5904                        self.epoch_schedule(),
5905                        &self.rent_collector,
5906                        is_startup,
5907                    );
5908            }
5909
5910            panic!(
5911                "capitalization_mismatch. slot: {}, calculated_lamports: {}, capitalization: {}",
5912                self.slot(),
5913                total_lamports,
5914                self.capitalization()
5915            );
5916        }
5917        accounts_hash
5918    }
5919
5920    /// Calculate the incremental accounts hash from `base_slot` to `self`
5921    pub fn update_incremental_accounts_hash(&self, base_slot: Slot) -> IncrementalAccountsHash {
5922        let config = CalcAccountsHashConfig {
5923            use_bg_thread_pool: true,
5924            ancestors: None, // does not matter, will not be used
5925            epoch_schedule: &self.epoch_schedule,
5926            rent_collector: &self.rent_collector,
5927            store_detailed_debug_info_on_failure: false,
5928        };
5929        let storages = self.get_snapshot_storages(Some(base_slot));
5930        let sorted_storages = SortedStorages::new(&storages);
5931        self.rc
5932            .accounts
5933            .accounts_db
5934            .update_incremental_accounts_hash(
5935                &config,
5936                &sorted_storages,
5937                self.slot(),
5938                HashStats::default(),
5939            )
5940            .0
5941    }
5942
5943    /// A snapshot bank should be purged of 0 lamport accounts which are not part of the hash
5944    /// calculation and could shield other real accounts.
5945    pub fn verify_snapshot_bank(
5946        &self,
5947        test_hash_calculation: bool,
5948        skip_shrink: bool,
5949        force_clean: bool,
5950        latest_full_snapshot_slot: Slot,
5951        base: Option<(Slot, /*capitalization*/ u64)>,
5952        duplicates_lt_hash: Option<Box<DuplicatesLtHash>>,
5953    ) -> bool {
5954        // If we verify the accounts using the lattice-based hash *and* with storages (as opposed
5955        // to the index), then we rely on the DuplicatesLtHash as given by generate_index().  Since
5956        // the duplicates are based on a specific set of storages, we must use the exact same
5957        // storages to do the lattice-based accounts verification.  This means we must wait to
5958        // clean/shrink until *after* we've gotten Arcs to the storages (this prevents their
5959        // untimely removal).  Simply, we call `verify_accounts_hash()` before we call `clean` or
5960        // `shrink`.
5961        let (verified_accounts, verify_accounts_time_us) = measure_us!({
5962            let should_verify_accounts = !self.rc.accounts.accounts_db.skip_initial_hash_calc;
5963            if should_verify_accounts {
5964                info!("Verifying accounts...");
5965                let verified = self.verify_accounts_hash(
5966                    base,
5967                    VerifyAccountsHashConfig {
5968                        test_hash_calculation,
5969                        ignore_mismatch: false,
5970                        require_rooted_bank: false,
5971                        run_in_background: true,
5972                        store_hash_raw_data_for_debug: false,
5973                    },
5974                    duplicates_lt_hash,
5975                );
5976                info!("Verifying accounts... In background.");
5977                verified
5978            } else {
5979                info!("Verifying accounts... Skipped.");
5980                self.rc
5981                    .accounts
5982                    .accounts_db
5983                    .verify_accounts_hash_in_bg
5984                    .verification_complete();
5985                true
5986            }
5987        });
5988
5989        let (_, clean_time_us) = measure_us!({
5990            let should_clean = force_clean || (!skip_shrink && self.slot() > 0);
5991            if should_clean {
5992                info!("Cleaning...");
5993                // We cannot clean past the latest full snapshot's slot because we are about to
5994                // perform an accounts hash calculation *up to that slot*.  If we cleaned *past*
5995                // that slot, then accounts could be removed from older storages, which would
5996                // change the accounts hash.
5997                self.rc.accounts.accounts_db.clean_accounts(
5998                    Some(latest_full_snapshot_slot),
5999                    true,
6000                    self.epoch_schedule(),
6001                    self.clean_accounts_old_storages_policy(),
6002                );
6003                info!("Cleaning... Done.");
6004            } else {
6005                info!("Cleaning... Skipped.");
6006            }
6007        });
6008
6009        let (_, shrink_time_us) = measure_us!({
6010            let should_shrink = !skip_shrink && self.slot() > 0;
6011            if should_shrink {
6012                info!("Shrinking...");
6013                self.rc.accounts.accounts_db.shrink_all_slots(
6014                    true,
6015                    self.epoch_schedule(),
6016                    // we cannot allow the snapshot slot to be shrunk
6017                    Some(self.slot()),
6018                );
6019                info!("Shrinking... Done.");
6020            } else {
6021                info!("Shrinking... Skipped.");
6022            }
6023        });
6024
6025        info!("Verifying bank...");
6026        let (verified_bank, verify_bank_time_us) = measure_us!(self.verify_hash());
6027        info!("Verifying bank... Done.");
6028
6029        datapoint_info!(
6030            "verify_snapshot_bank",
6031            ("clean_us", clean_time_us, i64),
6032            ("shrink_us", shrink_time_us, i64),
6033            ("verify_accounts_us", verify_accounts_time_us, i64),
6034            ("verify_bank_us", verify_bank_time_us, i64),
6035        );
6036
6037        verified_accounts && verified_bank
6038    }
6039
6040    /// Return the number of hashes per tick
6041    pub fn hashes_per_tick(&self) -> &Option<u64> {
6042        &self.hashes_per_tick
6043    }
6044
6045    /// Return the number of ticks per slot
6046    pub fn ticks_per_slot(&self) -> u64 {
6047        self.ticks_per_slot
6048    }
6049
6050    /// Return the number of slots per year
6051    pub fn slots_per_year(&self) -> f64 {
6052        self.slots_per_year
6053    }
6054
6055    /// Return the number of ticks since genesis.
6056    pub fn tick_height(&self) -> u64 {
6057        self.tick_height.load(Relaxed)
6058    }
6059
6060    /// Return the inflation parameters of the Bank
6061    pub fn inflation(&self) -> Inflation {
6062        *self.inflation.read().unwrap()
6063    }
6064
6065    /// Return the rent collector for this Bank
6066    pub fn rent_collector(&self) -> &RentCollector {
6067        &self.rent_collector
6068    }
6069
6070    /// Return the total capitalization of the Bank
6071    pub fn capitalization(&self) -> u64 {
6072        self.capitalization.load(Relaxed)
6073    }
6074
6075    /// Return this bank's max_tick_height
6076    pub fn max_tick_height(&self) -> u64 {
6077        self.max_tick_height
6078    }
6079
6080    /// Return the block_height of this bank
6081    pub fn block_height(&self) -> u64 {
6082        self.block_height
6083    }
6084
6085    /// Return the number of slots per epoch for the given epoch
6086    pub fn get_slots_in_epoch(&self, epoch: Epoch) -> u64 {
6087        self.epoch_schedule().get_slots_in_epoch(epoch)
6088    }
6089
6090    /// returns the epoch for which this bank's leader_schedule_slot_offset and slot would
6091    ///  need to cache leader_schedule
6092    pub fn get_leader_schedule_epoch(&self, slot: Slot) -> Epoch {
6093        self.epoch_schedule().get_leader_schedule_epoch(slot)
6094    }
6095
6096    /// a bank-level cache of vote accounts and stake delegation info
6097    fn update_stakes_cache(
6098        &self,
6099        txs: &[impl SVMMessage],
6100        processing_results: &[TransactionProcessingResult],
6101    ) {
6102        debug_assert_eq!(txs.len(), processing_results.len());
6103        let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
6104        txs.iter()
6105            .zip(processing_results)
6106            .filter_map(|(tx, processing_result)| {
6107                processing_result
6108                    .processed_transaction()
6109                    .map(|processed_tx| (tx, processed_tx))
6110            })
6111            .filter_map(|(tx, processed_tx)| {
6112                processed_tx
6113                    .executed_transaction()
6114                    .map(|executed_tx| (tx, executed_tx))
6115            })
6116            .filter(|(_, executed_tx)| executed_tx.was_successful())
6117            .flat_map(|(tx, executed_tx)| {
6118                let num_account_keys = tx.account_keys().len();
6119                let loaded_tx = &executed_tx.loaded_transaction;
6120                loaded_tx.accounts.iter().take(num_account_keys)
6121            })
6122            .for_each(|(pubkey, account)| {
6123                // note that this could get timed to: self.rc.accounts.accounts_db.stats.stakes_cache_check_and_store_us,
6124                //  but this code path is captured separately in ExecuteTimingType::UpdateStakesCacheUs
6125                self.stakes_cache
6126                    .check_and_store(pubkey, account, new_warmup_cooldown_rate_epoch);
6127            });
6128    }
6129
6130    /// current vote accounts for this bank along with the stake
6131    ///   attributed to each account
6132    pub fn vote_accounts(&self) -> Arc<VoteAccountsHashMap> {
6133        let stakes = self.stakes_cache.stakes();
6134        Arc::from(stakes.vote_accounts())
6135    }
6136
6137    /// Vote account for the given vote account pubkey.
6138    pub fn get_vote_account(&self, vote_account: &Pubkey) -> Option<VoteAccount> {
6139        let stakes = self.stakes_cache.stakes();
6140        let vote_account = stakes.vote_accounts().get(vote_account)?;
6141        Some(vote_account.clone())
6142    }
6143
6144    /// Get the EpochStakes for the current Bank::epoch
6145    pub fn current_epoch_stakes(&self) -> &EpochStakes {
6146        // The stakes for a given epoch (E) in self.epoch_stakes are keyed by leader schedule epoch
6147        // (E + 1) so the stakes for the current epoch are stored at self.epoch_stakes[E + 1]
6148        self.epoch_stakes
6149            .get(&self.epoch.saturating_add(1))
6150            .expect("Current epoch stakes must exist")
6151    }
6152
6153    /// Get the EpochStakes for a given epoch
6154    pub fn epoch_stakes(&self, epoch: Epoch) -> Option<&EpochStakes> {
6155        self.epoch_stakes.get(&epoch)
6156    }
6157
6158    pub fn epoch_stakes_map(&self) -> &HashMap<Epoch, EpochStakes> {
6159        &self.epoch_stakes
6160    }
6161
6162    /// Get the staked nodes map for the current Bank::epoch
6163    pub fn current_epoch_staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
6164        self.current_epoch_stakes().stakes().staked_nodes()
6165    }
6166
6167    pub fn epoch_staked_nodes(&self, epoch: Epoch) -> Option<Arc<HashMap<Pubkey, u64>>> {
6168        Some(self.epoch_stakes.get(&epoch)?.stakes().staked_nodes())
6169    }
6170
6171    /// Get the total epoch stake for the given epoch.
6172    pub fn epoch_total_stake(&self, epoch: Epoch) -> Option<u64> {
6173        self.epoch_stakes
6174            .get(&epoch)
6175            .map(|epoch_stakes| epoch_stakes.total_stake())
6176    }
6177
6178    /// Get the total epoch stake for the current Bank::epoch
6179    pub fn get_current_epoch_total_stake(&self) -> u64 {
6180        self.current_epoch_stakes().total_stake()
6181    }
6182
6183    /// vote accounts for the specific epoch along with the stake
6184    ///   attributed to each account
6185    pub fn epoch_vote_accounts(&self, epoch: Epoch) -> Option<&VoteAccountsHashMap> {
6186        let epoch_stakes = self.epoch_stakes.get(&epoch)?.stakes();
6187        Some(epoch_stakes.vote_accounts().as_ref())
6188    }
6189
6190    /// Get the vote accounts along with the stake attributed to each account
6191    /// for the current Bank::epoch
6192    pub fn get_current_epoch_vote_accounts(&self) -> &VoteAccountsHashMap {
6193        self.current_epoch_stakes()
6194            .stakes()
6195            .vote_accounts()
6196            .as_ref()
6197    }
6198
6199    /// Get the fixed authorized voter for the given vote account for the
6200    /// current epoch
6201    pub fn epoch_authorized_voter(&self, vote_account: &Pubkey) -> Option<&Pubkey> {
6202        self.epoch_stakes
6203            .get(&self.epoch)
6204            .expect("Epoch stakes for bank's own epoch must exist")
6205            .epoch_authorized_voters()
6206            .get(vote_account)
6207    }
6208
6209    /// Get the fixed set of vote accounts for the given node id for the
6210    /// current epoch
6211    pub fn epoch_vote_accounts_for_node_id(&self, node_id: &Pubkey) -> Option<&NodeVoteAccounts> {
6212        self.epoch_stakes
6213            .get(&self.epoch)
6214            .expect("Epoch stakes for bank's own epoch must exist")
6215            .node_id_to_vote_accounts()
6216            .get(node_id)
6217    }
6218
6219    /// Get the total stake belonging to vote accounts associated with the given node id for the
6220    /// given epoch.
6221    pub fn epoch_node_id_to_stake(&self, epoch: Epoch, node_id: &Pubkey) -> Option<u64> {
6222        self.epoch_stakes(epoch)
6223            .and_then(|epoch_stakes| epoch_stakes.node_id_to_stake(node_id))
6224    }
6225
6226    /// Get the fixed total stake of all vote accounts for current epoch
6227    pub fn total_epoch_stake(&self) -> u64 {
6228        self.epoch_stakes
6229            .get(&self.epoch)
6230            .expect("Epoch stakes for bank's own epoch must exist")
6231            .total_stake()
6232    }
6233
6234    /// Get the fixed stake of the given vote account for the current epoch
6235    pub fn epoch_vote_account_stake(&self, vote_account: &Pubkey) -> u64 {
6236        *self
6237            .epoch_vote_accounts(self.epoch())
6238            .expect("Bank epoch vote accounts must contain entry for the bank's own epoch")
6239            .get(vote_account)
6240            .map(|(stake, _)| stake)
6241            .unwrap_or(&0)
6242    }
6243
6244    /// given a slot, return the epoch and offset into the epoch this slot falls
6245    /// e.g. with a fixed number for slots_per_epoch, the calculation is simply:
6246    ///
6247    ///  ( slot/slots_per_epoch, slot % slots_per_epoch )
6248    ///
6249    pub fn get_epoch_and_slot_index(&self, slot: Slot) -> (Epoch, SlotIndex) {
6250        self.epoch_schedule().get_epoch_and_slot_index(slot)
6251    }
6252
6253    pub fn get_epoch_info(&self) -> EpochInfo {
6254        let absolute_slot = self.slot();
6255        let block_height = self.block_height();
6256        let (epoch, slot_index) = self.get_epoch_and_slot_index(absolute_slot);
6257        let slots_in_epoch = self.get_slots_in_epoch(epoch);
6258        let transaction_count = Some(self.transaction_count());
6259        EpochInfo {
6260            epoch,
6261            slot_index,
6262            slots_in_epoch,
6263            absolute_slot,
6264            block_height,
6265            transaction_count,
6266        }
6267    }
6268
6269    pub fn is_empty(&self) -> bool {
6270        !self.is_delta.load(Relaxed)
6271    }
6272
6273    pub fn add_mockup_builtin(
6274        &mut self,
6275        program_id: Pubkey,
6276        builtin_function: BuiltinFunctionWithContext,
6277    ) {
6278        self.transaction_processor.add_builtin(
6279            self,
6280            program_id,
6281            "mockup",
6282            ProgramCacheEntry::new_builtin(self.slot, 0, builtin_function),
6283        );
6284    }
6285
6286    pub fn add_precompile(&mut self, program_id: &Pubkey) {
6287        debug!("Adding precompiled program {}", program_id);
6288        self.add_precompiled_account(program_id);
6289        debug!("Added precompiled program {:?}", program_id);
6290    }
6291
6292    // Call AccountsDb::clean_accounts()
6293    //
6294    // This fn is meant to be called by the snapshot handler in Accounts Background Service.  If
6295    // calling from elsewhere, ensure the same invariants hold/expectations are met.
6296    pub(crate) fn clean_accounts(&self) {
6297        // Don't clean the slot we're snapshotting because it may have zero-lamport
6298        // accounts that were included in the bank delta hash when the bank was frozen,
6299        // and if we clean them here, any newly created snapshot's hash for this bank
6300        // may not match the frozen hash.
6301        //
6302        // So when we're snapshotting, the highest slot to clean is lowered by one.
6303        let highest_slot_to_clean = self.slot().saturating_sub(1);
6304
6305        self.rc.accounts.accounts_db.clean_accounts(
6306            Some(highest_slot_to_clean),
6307            false,
6308            self.epoch_schedule(),
6309            self.clean_accounts_old_storages_policy(),
6310        );
6311    }
6312
6313    pub fn print_accounts_stats(&self) {
6314        self.rc.accounts.accounts_db.print_accounts_stats("");
6315    }
6316
6317    pub fn shrink_candidate_slots(&self) -> usize {
6318        self.rc
6319            .accounts
6320            .accounts_db
6321            .shrink_candidate_slots(self.epoch_schedule())
6322    }
6323
6324    pub(crate) fn shrink_ancient_slots(&self) {
6325        // Invoke ancient slot shrinking only when the validator is
6326        // explicitly configured to do so. This condition may be
6327        // removed when the skip rewrites feature is enabled.
6328        if self.are_ancient_storages_enabled() {
6329            self.rc
6330                .accounts
6331                .accounts_db
6332                .shrink_ancient_slots(self.epoch_schedule())
6333        }
6334    }
6335
6336    /// Returns if ancient storages are enabled or not
6337    pub fn are_ancient_storages_enabled(&self) -> bool {
6338        let can_skip_rewrites = self.bank_hash_skips_rent_rewrites();
6339        let test_skip_rewrites_but_include_in_bank_hash = self
6340            .rc
6341            .accounts
6342            .accounts_db
6343            .test_skip_rewrites_but_include_in_bank_hash;
6344        can_skip_rewrites || test_skip_rewrites_but_include_in_bank_hash
6345    }
6346
6347    /// Returns how clean_accounts() should handle old storages
6348    fn clean_accounts_old_storages_policy(&self) -> OldStoragesPolicy {
6349        if self.are_ancient_storages_enabled() {
6350            OldStoragesPolicy::Leave
6351        } else {
6352            OldStoragesPolicy::Clean
6353        }
6354    }
6355
6356    pub fn read_cost_tracker(&self) -> LockResult<RwLockReadGuard<CostTracker>> {
6357        self.cost_tracker.read()
6358    }
6359
6360    pub fn write_cost_tracker(&self) -> LockResult<RwLockWriteGuard<CostTracker>> {
6361        self.cost_tracker.write()
6362    }
6363
6364    // Check if the wallclock time from bank creation to now has exceeded the allotted
6365    // time for transaction processing
6366    pub fn should_bank_still_be_processing_txs(
6367        bank_creation_time: &Instant,
6368        max_tx_ingestion_nanos: u128,
6369    ) -> bool {
6370        // Do this check outside of the PoH lock, hence not a method on PohRecorder
6371        bank_creation_time.elapsed().as_nanos() <= max_tx_ingestion_nanos
6372    }
6373
6374    pub fn deactivate_feature(&mut self, id: &Pubkey) {
6375        let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6376        feature_set.active.remove(id);
6377        feature_set.inactive.insert(*id);
6378        self.feature_set = Arc::new(feature_set);
6379    }
6380
6381    pub fn activate_feature(&mut self, id: &Pubkey) {
6382        let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6383        feature_set.inactive.remove(id);
6384        feature_set.active.insert(*id, 0);
6385        self.feature_set = Arc::new(feature_set);
6386    }
6387
6388    pub fn fill_bank_with_ticks_for_tests(&self) {
6389        self.do_fill_bank_with_ticks_for_tests(&BankWithScheduler::no_scheduler_available())
6390    }
6391
6392    pub(crate) fn do_fill_bank_with_ticks_for_tests(&self, scheduler: &InstalledSchedulerRwLock) {
6393        if self.tick_height.load(Relaxed) < self.max_tick_height {
6394            let last_blockhash = self.last_blockhash();
6395            while self.last_blockhash() == last_blockhash {
6396                self.register_tick(&Hash::new_unique(), scheduler)
6397            }
6398        } else {
6399            warn!("Bank already reached max tick height, cannot fill it with more ticks");
6400        }
6401    }
6402
6403    /// Get a set of all actively reserved account keys that are not allowed to
6404    /// be write-locked during transaction processing.
6405    pub fn get_reserved_account_keys(&self) -> &HashSet<Pubkey> {
6406        &self.reserved_account_keys.active
6407    }
6408
6409    // This is called from snapshot restore AND for each epoch boundary
6410    // The entire code path herein must be idempotent
6411    fn apply_feature_activations(
6412        &mut self,
6413        caller: ApplyFeatureActivationsCaller,
6414        debug_do_not_add_builtins: bool,
6415    ) {
6416        use ApplyFeatureActivationsCaller as Caller;
6417        let allow_new_activations = match caller {
6418            Caller::FinishInit => false,
6419            Caller::NewFromParent => true,
6420            Caller::WarpFromParent => false,
6421        };
6422        let (feature_set, new_feature_activations) =
6423            self.compute_active_feature_set(allow_new_activations);
6424        self.feature_set = Arc::new(feature_set);
6425
6426        // Update activation slot of features in `new_feature_activations`
6427        for feature_id in new_feature_activations.iter() {
6428            if let Some(mut account) = self.get_account_with_fixed_root(feature_id) {
6429                if let Some(mut feature) = feature::from_account(&account) {
6430                    feature.activated_at = Some(self.slot());
6431                    if feature::to_account(&feature, &mut account).is_some() {
6432                        self.store_account(feature_id, &account);
6433                    }
6434                    info!("Feature {} activated at slot {}", feature_id, self.slot());
6435                }
6436            }
6437        }
6438
6439        // Update active set of reserved account keys which are not allowed to be write locked
6440        self.reserved_account_keys = {
6441            let mut reserved_keys = ReservedAccountKeys::clone(&self.reserved_account_keys);
6442            reserved_keys.update_active_set(&self.feature_set);
6443            Arc::new(reserved_keys)
6444        };
6445
6446        if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
6447            *self.inflation.write().unwrap() = Inflation::pico();
6448            self.fee_rate_governor.burn_percent = 50; // 50% fee burn
6449            self.rent_collector.rent.burn_percent = 50; // 50% rent burn
6450        }
6451
6452        if !new_feature_activations.is_disjoint(&self.feature_set.full_inflation_features_enabled())
6453        {
6454            *self.inflation.write().unwrap() = Inflation::full();
6455            self.fee_rate_governor.burn_percent = 50; // 50% fee burn
6456            self.rent_collector.rent.burn_percent = 50; // 50% rent burn
6457        }
6458
6459        if !debug_do_not_add_builtins {
6460            self.apply_builtin_program_feature_transitions(
6461                allow_new_activations,
6462                &new_feature_activations,
6463            );
6464        }
6465
6466        if new_feature_activations.contains(&feature_set::update_hashes_per_tick::id()) {
6467            self.apply_updated_hashes_per_tick(DEFAULT_HASHES_PER_TICK);
6468        }
6469
6470        if new_feature_activations.contains(&feature_set::update_hashes_per_tick2::id()) {
6471            self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK2);
6472        }
6473
6474        if new_feature_activations.contains(&feature_set::update_hashes_per_tick3::id()) {
6475            self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK3);
6476        }
6477
6478        if new_feature_activations.contains(&feature_set::update_hashes_per_tick4::id()) {
6479            self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK4);
6480        }
6481
6482        if new_feature_activations.contains(&feature_set::update_hashes_per_tick5::id()) {
6483            self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK5);
6484        }
6485
6486        if new_feature_activations.contains(&feature_set::update_hashes_per_tick6::id()) {
6487            self.apply_updated_hashes_per_tick(UPDATED_HASHES_PER_TICK6);
6488        }
6489
6490        if new_feature_activations.contains(&feature_set::accounts_lt_hash::id()) {
6491            // Activating the accounts lt hash feature means we need to have an accounts lt hash
6492            // value at the end of this if-block.  If the cli arg has been used, that means we
6493            // already have an accounts lt hash and do not need to recalculate it.
6494            if self
6495                .rc
6496                .accounts
6497                .accounts_db
6498                .is_experimental_accumulator_hash_enabled()
6499            {
6500                // We already have an accounts lt hash value, so no need to recalculate it.
6501                // Nothing else to do here.
6502            } else {
6503                let parent_slot = self.parent_slot;
6504                info!(
6505                    "Calculating the accounts lt hash for slot {parent_slot} \
6506                     as part of feature activation; this may take some time...",
6507                );
6508                // We must calculate the accounts lt hash now as part of feature activation.
6509                // Note, this bank is *not* frozen yet, which means it will later call
6510                // `update_accounts_lt_hash()`.  Therefore, we calculate the accounts lt hash based
6511                // on *our parent*, not us!
6512                let parent_ancestors = {
6513                    let mut ancestors = self.ancestors.clone();
6514                    ancestors.remove(&self.slot());
6515                    ancestors
6516                };
6517                let (parent_accounts_lt_hash, duration) = meas_dur!({
6518                    self.rc
6519                        .accounts
6520                        .accounts_db
6521                        .calculate_accounts_lt_hash_at_startup_from_index(
6522                            &parent_ancestors,
6523                            parent_slot,
6524                        )
6525                });
6526                *self.accounts_lt_hash.get_mut().unwrap() = parent_accounts_lt_hash;
6527                info!(
6528                    "Calculating the accounts lt hash for slot {parent_slot} \
6529                     completed in {duration:?}, accounts_lt_hash checksum: {}",
6530                    self.accounts_lt_hash.get_mut().unwrap().0.checksum(),
6531                );
6532            }
6533        }
6534
6535        if new_feature_activations.contains(&feature_set::raise_block_limits_to_50m::id()) {
6536            let (account_cost_limit, block_cost_limit, vote_cost_limit) = simd_0207_block_limits();
6537            self.write_cost_tracker().unwrap().set_limits(
6538                account_cost_limit,
6539                block_cost_limit,
6540                vote_cost_limit,
6541            );
6542        }
6543    }
6544
6545    fn apply_updated_hashes_per_tick(&mut self, hashes_per_tick: u64) {
6546        info!(
6547            "Activating update_hashes_per_tick {} at slot {}",
6548            hashes_per_tick,
6549            self.slot(),
6550        );
6551        self.hashes_per_tick = Some(hashes_per_tick);
6552    }
6553
6554    fn adjust_sysvar_balance_for_rent(&self, account: &mut AccountSharedData) {
6555        account.set_lamports(
6556            self.get_minimum_balance_for_rent_exemption(account.data().len())
6557                .max(account.lamports()),
6558        );
6559    }
6560
6561    /// Compute the active feature set based on the current bank state,
6562    /// and return it together with the set of newly activated features.
6563    fn compute_active_feature_set(&self, include_pending: bool) -> (FeatureSet, AHashSet<Pubkey>) {
6564        let mut active = self.feature_set.active.clone();
6565        let mut inactive = AHashSet::new();
6566        let mut pending = AHashSet::new();
6567        let slot = self.slot();
6568
6569        for feature_id in &self.feature_set.inactive {
6570            let mut activated = None;
6571            if let Some(account) = self.get_account_with_fixed_root(feature_id) {
6572                if let Some(feature) = feature::from_account(&account) {
6573                    match feature.activated_at {
6574                        None if include_pending => {
6575                            // Feature activation is pending
6576                            pending.insert(*feature_id);
6577                            activated = Some(slot);
6578                        }
6579                        Some(activation_slot) if slot >= activation_slot => {
6580                            // Feature has been activated already
6581                            activated = Some(activation_slot);
6582                        }
6583                        _ => {}
6584                    }
6585                }
6586            }
6587            if let Some(slot) = activated {
6588                active.insert(*feature_id, slot);
6589            } else {
6590                inactive.insert(*feature_id);
6591            }
6592        }
6593
6594        (FeatureSet { active, inactive }, pending)
6595    }
6596
6597    fn apply_builtin_program_feature_transitions(
6598        &mut self,
6599        only_apply_transitions_for_new_features: bool,
6600        new_feature_activations: &AHashSet<Pubkey>,
6601    ) {
6602        for builtin in BUILTINS.iter() {
6603            // The `builtin_is_bpf` flag is used to handle the case where a
6604            // builtin is scheduled to be enabled by one feature gate and
6605            // later migrated to Core BPF by another.
6606            //
6607            // There should never be a case where a builtin is set to be
6608            // migrated to Core BPF and is also set to be enabled on feature
6609            // activation on the same feature gate. However, the
6610            // `builtin_is_bpf` flag will handle this case as well, electing
6611            // to first attempt the migration to Core BPF.
6612            //
6613            // The migration to Core BPF will fail gracefully because the
6614            // program account will not exist. The builtin will subsequently
6615            // be enabled, but it will never be migrated to Core BPF.
6616            //
6617            // Using the same feature gate for both enabling and migrating a
6618            // builtin to Core BPF should be strictly avoided.
6619            let mut builtin_is_bpf = false;
6620            if let Some(core_bpf_migration_config) = &builtin.core_bpf_migration_config {
6621                // If the builtin is set to be migrated to Core BPF on feature
6622                // activation, perform the migration and do not add the program
6623                // to the bank's builtins. The migration will remove it from
6624                // the builtins list and the cache.
6625                if new_feature_activations.contains(&core_bpf_migration_config.feature_id) {
6626                    if let Err(e) = self
6627                        .migrate_builtin_to_core_bpf(&builtin.program_id, core_bpf_migration_config)
6628                    {
6629                        warn!(
6630                            "Failed to migrate builtin {} to Core BPF: {}",
6631                            builtin.name, e
6632                        );
6633                    } else {
6634                        builtin_is_bpf = true;
6635                    }
6636                } else {
6637                    // If the builtin has already been migrated to Core BPF, do not
6638                    // add it to the bank's builtins.
6639                    builtin_is_bpf = self
6640                        .get_account(&builtin.program_id)
6641                        .map(|a| a.owner() == &bpf_loader_upgradeable::id())
6642                        .unwrap_or(false);
6643                }
6644            };
6645
6646            if let Some(feature_id) = builtin.enable_feature_id {
6647                let should_enable_builtin_on_feature_transition = !builtin_is_bpf
6648                    && if only_apply_transitions_for_new_features {
6649                        new_feature_activations.contains(&feature_id)
6650                    } else {
6651                        self.feature_set.is_active(&feature_id)
6652                    };
6653
6654                if should_enable_builtin_on_feature_transition {
6655                    self.transaction_processor.add_builtin(
6656                        self,
6657                        builtin.program_id,
6658                        builtin.name,
6659                        ProgramCacheEntry::new_builtin(
6660                            self.feature_set.activated_slot(&feature_id).unwrap_or(0),
6661                            builtin.name.len(),
6662                            builtin.entrypoint,
6663                        ),
6664                    );
6665                }
6666            }
6667        }
6668
6669        // Migrate any necessary stateless builtins to core BPF.
6670        // Stateless builtins do not have an `enable_feature_id` since they
6671        // do not exist on-chain.
6672        for stateless_builtin in STATELESS_BUILTINS.iter() {
6673            if let Some(core_bpf_migration_config) = &stateless_builtin.core_bpf_migration_config {
6674                if new_feature_activations.contains(&core_bpf_migration_config.feature_id) {
6675                    if let Err(e) = self.migrate_builtin_to_core_bpf(
6676                        &stateless_builtin.program_id,
6677                        core_bpf_migration_config,
6678                    ) {
6679                        warn!(
6680                            "Failed to migrate stateless builtin {} to Core BPF: {}",
6681                            stateless_builtin.name, e
6682                        );
6683                    }
6684                }
6685            }
6686        }
6687
6688        for precompile in get_precompiles() {
6689            let should_add_precompile = precompile
6690                .feature
6691                .as_ref()
6692                .map(|feature_id| self.feature_set.is_active(feature_id))
6693                .unwrap_or(false);
6694            if should_add_precompile {
6695                self.add_precompile(&precompile.program_id);
6696            }
6697        }
6698    }
6699
6700    /// Use to replace programs by feature activation
6701    #[allow(dead_code)]
6702    fn replace_program_account(
6703        &mut self,
6704        old_address: &Pubkey,
6705        new_address: &Pubkey,
6706        datapoint_name: &'static str,
6707    ) {
6708        if let Some(old_account) = self.get_account_with_fixed_root(old_address) {
6709            if let Some(new_account) = self.get_account_with_fixed_root(new_address) {
6710                datapoint_info!(datapoint_name, ("slot", self.slot, i64));
6711
6712                // Burn lamports in the old account
6713                self.capitalization
6714                    .fetch_sub(old_account.lamports(), Relaxed);
6715
6716                // Transfer new account to old account
6717                self.store_account(old_address, &new_account);
6718
6719                // Clear new account
6720                self.store_account(new_address, &AccountSharedData::default());
6721
6722                // Unload a program from the bank's cache
6723                self.transaction_processor
6724                    .program_cache
6725                    .write()
6726                    .unwrap()
6727                    .remove_programs([*old_address].into_iter());
6728
6729                self.calculate_and_update_accounts_data_size_delta_off_chain(
6730                    old_account.data().len(),
6731                    new_account.data().len(),
6732                );
6733            }
6734        }
6735    }
6736
6737    /// Get all the accounts for this bank and calculate stats
6738    pub fn get_total_accounts_stats(&self) -> ScanResult<TotalAccountsStats> {
6739        let accounts = self.get_all_accounts(false)?;
6740        Ok(self.calculate_total_accounts_stats(
6741            accounts
6742                .iter()
6743                .map(|(pubkey, account, _slot)| (pubkey, account)),
6744        ))
6745    }
6746
6747    /// Given all the accounts for a bank, calculate stats
6748    pub fn calculate_total_accounts_stats<'a>(
6749        &self,
6750        accounts: impl Iterator<Item = (&'a Pubkey, &'a AccountSharedData)>,
6751    ) -> TotalAccountsStats {
6752        let rent_collector = self.rent_collector();
6753        let mut total_accounts_stats = TotalAccountsStats::default();
6754        accounts.for_each(|(pubkey, account)| {
6755            total_accounts_stats.accumulate_account(pubkey, account, rent_collector);
6756        });
6757
6758        total_accounts_stats
6759    }
6760
6761    /// Get the EAH that will be used by snapshots
6762    ///
6763    /// Since snapshots are taken on roots, if the bank is in the EAH calculation window then an
6764    /// EAH *must* be included.  This means if an EAH calculation is currently in-flight we will
6765    /// wait for it to complete.
6766    pub fn get_epoch_accounts_hash_to_serialize(&self) -> Option<EpochAccountsHash> {
6767        let should_get_epoch_accounts_hash = epoch_accounts_hash_utils::is_enabled_this_epoch(self)
6768            && epoch_accounts_hash_utils::is_in_calculation_window(self);
6769        if !should_get_epoch_accounts_hash {
6770            return None;
6771        }
6772
6773        let (epoch_accounts_hash, waiting_time_us) = measure_us!(self
6774            .rc
6775            .accounts
6776            .accounts_db
6777            .epoch_accounts_hash_manager
6778            .wait_get_epoch_accounts_hash());
6779
6780        datapoint_info!(
6781            "bank-get_epoch_accounts_hash_to_serialize",
6782            ("slot", self.slot(), i64),
6783            ("waiting-time-us", waiting_time_us, i64),
6784        );
6785        Some(epoch_accounts_hash)
6786    }
6787
6788    /// Convenience fn to get the Epoch Accounts Hash
6789    pub fn epoch_accounts_hash(&self) -> Option<EpochAccountsHash> {
6790        self.rc
6791            .accounts
6792            .accounts_db
6793            .epoch_accounts_hash_manager
6794            .try_get_epoch_accounts_hash()
6795    }
6796
6797    pub fn is_in_slot_hashes_history(&self, slot: &Slot) -> bool {
6798        if slot < &self.slot {
6799            if let Ok(slot_hashes) = self.transaction_processor.sysvar_cache().get_slot_hashes() {
6800                return slot_hashes.get(slot).is_some();
6801            }
6802        }
6803        false
6804    }
6805
6806    pub fn check_program_modification_slot(&self) -> bool {
6807        self.check_program_modification_slot
6808    }
6809
6810    pub fn set_check_program_modification_slot(&mut self, check: bool) {
6811        self.check_program_modification_slot = check;
6812    }
6813
6814    pub fn fee_structure(&self) -> &FeeStructure {
6815        &self.fee_structure
6816    }
6817
6818    pub fn block_id(&self) -> Option<Hash> {
6819        *self.block_id.read().unwrap()
6820    }
6821
6822    pub fn set_block_id(&self, block_id: Option<Hash>) {
6823        *self.block_id.write().unwrap() = block_id;
6824    }
6825
6826    pub fn compute_budget(&self) -> Option<ComputeBudget> {
6827        self.compute_budget
6828    }
6829
6830    pub fn add_builtin(&self, program_id: Pubkey, name: &str, builtin: ProgramCacheEntry) {
6831        self.transaction_processor
6832            .add_builtin(self, program_id, name, builtin)
6833    }
6834
6835    pub fn get_bank_hash_stats(&self) -> BankHashStats {
6836        self.bank_hash_stats.load()
6837    }
6838}
6839
6840impl TransactionProcessingCallback for Bank {
6841    fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize> {
6842        self.rc
6843            .accounts
6844            .accounts_db
6845            .account_matches_owners(&self.ancestors, account, owners)
6846            .ok()
6847    }
6848
6849    fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
6850        self.rc
6851            .accounts
6852            .accounts_db
6853            .load_with_fixed_root(&self.ancestors, pubkey)
6854            .map(|(acc, _)| acc)
6855    }
6856
6857    // NOTE: must hold idempotent for the same set of arguments
6858    /// Add a builtin program account
6859    fn add_builtin_account(&self, name: &str, program_id: &Pubkey) {
6860        let existing_genuine_program =
6861            self.get_account_with_fixed_root(program_id)
6862                .and_then(|account| {
6863                    // it's very unlikely to be squatted at program_id as non-system account because of burden to
6864                    // find victim's pubkey/hash. So, when account.owner is indeed native_loader's, it's
6865                    // safe to assume it's a genuine program.
6866                    if native_loader::check_id(account.owner()) {
6867                        Some(account)
6868                    } else {
6869                        // malicious account is pre-occupying at program_id
6870                        self.burn_and_purge_account(program_id, account);
6871                        None
6872                    }
6873                });
6874
6875        // introducing builtin program
6876        if existing_genuine_program.is_some() {
6877            // The existing account is sufficient
6878            return;
6879        }
6880
6881        assert!(
6882            !self.freeze_started(),
6883            "Can't change frozen bank by adding not-existing new builtin program ({name}, {program_id}). \
6884            Maybe, inconsistent program activation is detected on snapshot restore?"
6885        );
6886
6887        // Add a bogus executable builtin account, which will be loaded and ignored.
6888        let account = native_loader::create_loadable_account_with_fields(
6889            name,
6890            self.inherit_specially_retained_account_fields(&existing_genuine_program),
6891        );
6892        self.store_account_and_update_capitalization(program_id, &account);
6893    }
6894
6895    fn inspect_account(&self, address: &Pubkey, account_state: AccountState, is_writable: bool) {
6896        if self.is_accounts_lt_hash_enabled() {
6897            self.inspect_account_for_accounts_lt_hash(address, &account_state, is_writable);
6898        }
6899    }
6900
6901    fn get_current_epoch_vote_account_stake(&self, vote_address: &Pubkey) -> u64 {
6902        self.get_current_epoch_vote_accounts()
6903            .get(vote_address)
6904            .map(|(stake, _)| (*stake))
6905            .unwrap_or(0)
6906    }
6907
6908    fn calculate_fee(
6909        &self,
6910        message: &impl SVMMessage,
6911        lamports_per_signature: u64,
6912        prioritization_fee: u64,
6913        feature_set: &FeatureSet,
6914    ) -> FeeDetails {
6915        solana_fee::calculate_fee_details(
6916            message,
6917            false, /* zero_fees_for_test */
6918            lamports_per_signature,
6919            prioritization_fee,
6920            FeeFeatures::from(feature_set),
6921        )
6922    }
6923}
6924
6925#[cfg(feature = "dev-context-only-utils")]
6926impl Bank {
6927    pub fn wrap_with_bank_forks_for_tests(self) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6928        let bank_forks = BankForks::new_rw_arc(self);
6929        let bank = bank_forks.read().unwrap().root_bank();
6930        (bank, bank_forks)
6931    }
6932
6933    pub fn default_for_tests() -> Self {
6934        let accounts_db = AccountsDb::default_for_tests();
6935        let accounts = Accounts::new(Arc::new(accounts_db));
6936        Self::default_with_accounts(accounts)
6937    }
6938
6939    pub fn new_with_bank_forks_for_tests(
6940        genesis_config: &GenesisConfig,
6941    ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6942        let bank = Self::new_for_tests(genesis_config);
6943        bank.wrap_with_bank_forks_for_tests()
6944    }
6945
6946    pub fn new_for_tests(genesis_config: &GenesisConfig) -> Self {
6947        Self::new_with_config_for_tests(genesis_config, BankTestConfig::default())
6948    }
6949
6950    pub fn new_with_mockup_builtin_for_tests(
6951        genesis_config: &GenesisConfig,
6952        program_id: Pubkey,
6953        builtin_function: BuiltinFunctionWithContext,
6954    ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6955        let mut bank = Self::new_for_tests(genesis_config);
6956        bank.add_mockup_builtin(program_id, builtin_function);
6957        bank.wrap_with_bank_forks_for_tests()
6958    }
6959
6960    pub fn new_no_wallclock_throttle_for_tests(
6961        genesis_config: &GenesisConfig,
6962    ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6963        let mut bank = Self::new_for_tests(genesis_config);
6964
6965        bank.ns_per_slot = u128::MAX;
6966        bank.wrap_with_bank_forks_for_tests()
6967    }
6968
6969    pub fn new_with_config_for_tests(
6970        genesis_config: &GenesisConfig,
6971        test_config: BankTestConfig,
6972    ) -> Self {
6973        Self::new_with_paths_for_tests(
6974            genesis_config,
6975            Arc::new(RuntimeConfig::default()),
6976            test_config,
6977            Vec::new(),
6978        )
6979    }
6980
6981    pub fn new_with_paths_for_tests(
6982        genesis_config: &GenesisConfig,
6983        runtime_config: Arc<RuntimeConfig>,
6984        test_config: BankTestConfig,
6985        paths: Vec<PathBuf>,
6986    ) -> Self {
6987        Self::new_with_paths(
6988            genesis_config,
6989            runtime_config,
6990            paths,
6991            None,
6992            None,
6993            false,
6994            Some(test_config.accounts_db_config),
6995            None,
6996            Some(Pubkey::new_unique()),
6997            Arc::default(),
6998            None,
6999            None,
7000        )
7001    }
7002
7003    pub fn new_for_benches(genesis_config: &GenesisConfig) -> Self {
7004        Self::new_with_paths_for_benches(genesis_config, Vec::new())
7005    }
7006
7007    /// Intended for use by benches only.
7008    /// create new bank with the given config and paths.
7009    pub fn new_with_paths_for_benches(genesis_config: &GenesisConfig, paths: Vec<PathBuf>) -> Self {
7010        Self::new_with_paths(
7011            genesis_config,
7012            Arc::<RuntimeConfig>::default(),
7013            paths,
7014            None,
7015            None,
7016            false,
7017            Some(ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS),
7018            None,
7019            Some(Pubkey::new_unique()),
7020            Arc::default(),
7021            None,
7022            None,
7023        )
7024    }
7025
7026    /// Prepare a transaction batch from a list of legacy transactions. Used for tests only.
7027    #[cfg(feature = "dev-context-only-utils")]
7028    pub fn prepare_batch_for_tests(
7029        &self,
7030        txs: Vec<Transaction>,
7031    ) -> TransactionBatch<RuntimeTransaction<SanitizedTransaction>> {
7032        let transaction_account_lock_limit = self.get_transaction_account_lock_limit();
7033        let sanitized_txs = txs
7034            .into_iter()
7035            .map(RuntimeTransaction::from_transaction_for_tests)
7036            .collect::<Vec<_>>();
7037        let lock_results = self
7038            .rc
7039            .accounts
7040            .lock_accounts(sanitized_txs.iter(), transaction_account_lock_limit);
7041        TransactionBatch::new(lock_results, self, OwnedOrBorrowed::Owned(sanitized_txs))
7042    }
7043
7044    /// Set the initial accounts data size
7045    /// NOTE: This fn is *ONLY FOR TESTS*
7046    pub fn set_accounts_data_size_initial_for_tests(&mut self, amount: u64) {
7047        self.accounts_data_size_initial = amount;
7048    }
7049
7050    /// Update the accounts data size off-chain delta
7051    /// NOTE: This fn is *ONLY FOR TESTS*
7052    pub fn update_accounts_data_size_delta_off_chain_for_tests(&self, amount: i64) {
7053        self.update_accounts_data_size_delta_off_chain(amount)
7054    }
7055
7056    #[cfg(test)]
7057    fn restore_old_behavior_for_fragile_tests(&self) {
7058        self.lazy_rent_collection.store(true, Relaxed);
7059    }
7060
7061    /// Process multiple transaction in a single batch. This is used for benches and unit tests.
7062    ///
7063    /// # Panics
7064    ///
7065    /// Panics if any of the transactions do not pass sanitization checks.
7066    #[must_use]
7067    pub fn process_transactions<'a>(
7068        &self,
7069        txs: impl Iterator<Item = &'a Transaction>,
7070    ) -> Vec<Result<()>> {
7071        self.try_process_transactions(txs).unwrap()
7072    }
7073
7074    /// Process entry transactions in a single batch. This is used for benches and unit tests.
7075    ///
7076    /// # Panics
7077    ///
7078    /// Panics if any of the transactions do not pass sanitization checks.
7079    #[must_use]
7080    pub fn process_entry_transactions(&self, txs: Vec<VersionedTransaction>) -> Vec<Result<()>> {
7081        self.try_process_entry_transactions(txs).unwrap()
7082    }
7083
7084    #[cfg(test)]
7085    pub fn flush_accounts_cache_slot_for_tests(&self) {
7086        self.rc
7087            .accounts
7088            .accounts_db
7089            .flush_accounts_cache_slot_for_tests(self.slot())
7090    }
7091
7092    /// This is only valid to call from tests.
7093    /// block until initial accounts hash verification has completed
7094    pub fn wait_for_initial_accounts_hash_verification_completed_for_tests(&self) {
7095        self.rc
7096            .accounts
7097            .accounts_db
7098            .verify_accounts_hash_in_bg
7099            .join_background_thread()
7100    }
7101
7102    pub fn get_sysvar_cache_for_tests(&self) -> SysvarCache {
7103        self.transaction_processor.get_sysvar_cache_for_tests()
7104    }
7105
7106    pub fn update_accounts_hash_for_tests(&self) -> AccountsHash {
7107        self.update_accounts_hash(CalcAccountsHashDataSource::IndexForTests, false, false)
7108    }
7109
7110    pub fn new_program_cache_for_tx_batch_for_slot(&self, slot: Slot) -> ProgramCacheForTxBatch {
7111        ProgramCacheForTxBatch::new_from_cache(
7112            slot,
7113            self.epoch_schedule.get_epoch(slot),
7114            &self.transaction_processor.program_cache.read().unwrap(),
7115        )
7116    }
7117
7118    pub fn get_transaction_processor(&self) -> &TransactionBatchProcessor<BankForks> {
7119        &self.transaction_processor
7120    }
7121
7122    pub fn set_fee_structure(&mut self, fee_structure: &FeeStructure) {
7123        self.fee_structure = fee_structure.clone();
7124    }
7125
7126    pub fn load_program(
7127        &self,
7128        pubkey: &Pubkey,
7129        reload: bool,
7130        effective_epoch: Epoch,
7131    ) -> Option<Arc<ProgramCacheEntry>> {
7132        let environments = self
7133            .transaction_processor
7134            .get_environments_for_epoch(effective_epoch)?;
7135        load_program_with_pubkey(
7136            self,
7137            &environments,
7138            pubkey,
7139            self.slot(),
7140            &mut ExecuteTimings::default(), // Called by ledger-tool, metrics not accumulated.
7141            reload,
7142        )
7143    }
7144
7145    pub fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
7146        match self.get_account_with_fixed_root(pubkey) {
7147            Some(mut account) => {
7148                let min_balance = match get_system_account_kind(&account) {
7149                    Some(SystemAccountKind::Nonce) => self
7150                        .rent_collector
7151                        .rent
7152                        .minimum_balance(nonce::State::size()),
7153                    _ => 0,
7154                };
7155
7156                lamports
7157                    .checked_add(min_balance)
7158                    .filter(|required_balance| *required_balance <= account.lamports())
7159                    .ok_or(TransactionError::InsufficientFundsForFee)?;
7160                account
7161                    .checked_sub_lamports(lamports)
7162                    .map_err(|_| TransactionError::InsufficientFundsForFee)?;
7163                self.store_account(pubkey, &account);
7164
7165                Ok(())
7166            }
7167            None => Err(TransactionError::AccountNotFound),
7168        }
7169    }
7170
7171    pub fn set_hash_overrides(&self, hash_overrides: HashOverrides) {
7172        *self.hash_overrides.lock().unwrap() = hash_overrides;
7173    }
7174}
7175
7176/// Compute how much an account has changed size.  This function is useful when the data size delta
7177/// needs to be computed and passed to an `update_accounts_data_size_delta` function.
7178fn calculate_data_size_delta(old_data_size: usize, new_data_size: usize) -> i64 {
7179    assert!(old_data_size <= i64::MAX as usize);
7180    assert!(new_data_size <= i64::MAX as usize);
7181    let old_data_size = old_data_size as i64;
7182    let new_data_size = new_data_size as i64;
7183
7184    new_data_size.saturating_sub(old_data_size)
7185}
7186
7187/// Since `apply_feature_activations()` has different behavior depending on its caller, enumerate
7188/// those callers explicitly.
7189#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7190enum ApplyFeatureActivationsCaller {
7191    FinishInit,
7192    NewFromParent,
7193    WarpFromParent,
7194}
7195
7196/// Return the computed values from `collect_rent_from_accounts()`
7197///
7198/// Since `collect_rent_from_accounts()` is running in parallel, instead of updating the
7199/// atomics/shared data inside this function, return those values in this struct for the caller to
7200/// process later.
7201#[derive(Debug, Default)]
7202struct CollectRentFromAccountsInfo {
7203    skipped_rewrites: Vec<(Pubkey, AccountHash)>,
7204    rent_collected_info: CollectedInfo,
7205    rent_rewards: Vec<(Pubkey, RewardInfo)>,
7206    time_collecting_rent_us: u64,
7207    time_storing_accounts_us: u64,
7208    num_accounts: usize,
7209}
7210
7211/// Return the computed values—of each iteration in the parallel loop inside
7212/// `collect_rent_in_partition()`—and then perform a reduce on all of them.
7213#[derive(Debug, Default)]
7214struct CollectRentInPartitionInfo {
7215    skipped_rewrites: Vec<(Pubkey, AccountHash)>,
7216    rent_collected: u64,
7217    accounts_data_size_reclaimed: u64,
7218    rent_rewards: Vec<(Pubkey, RewardInfo)>,
7219    time_loading_accounts_us: u64,
7220    time_collecting_rent_us: u64,
7221    time_storing_accounts_us: u64,
7222    num_accounts: usize,
7223}
7224
7225impl CollectRentInPartitionInfo {
7226    /// Create a new `CollectRentInPartitionInfo` from the results of loading accounts and
7227    /// collecting rent on them.
7228    #[must_use]
7229    fn new(info: CollectRentFromAccountsInfo, time_loading_accounts: Duration) -> Self {
7230        Self {
7231            skipped_rewrites: info.skipped_rewrites,
7232            rent_collected: info.rent_collected_info.rent_amount,
7233            accounts_data_size_reclaimed: info.rent_collected_info.account_data_len_reclaimed,
7234            rent_rewards: info.rent_rewards,
7235            time_loading_accounts_us: time_loading_accounts.as_micros() as u64,
7236            time_collecting_rent_us: info.time_collecting_rent_us,
7237            time_storing_accounts_us: info.time_storing_accounts_us,
7238            num_accounts: info.num_accounts,
7239        }
7240    }
7241
7242    /// Reduce (i.e. 'combine') two `CollectRentInPartitionInfo`s into one.
7243    ///
7244    /// This fn is used by `collect_rent_in_partition()` as the reduce step (of map-reduce) in its
7245    /// parallel loop of rent collection.
7246    #[must_use]
7247    fn reduce(lhs: Self, rhs: Self) -> Self {
7248        Self {
7249            skipped_rewrites: [lhs.skipped_rewrites, rhs.skipped_rewrites].concat(),
7250            rent_collected: lhs.rent_collected.saturating_add(rhs.rent_collected),
7251            accounts_data_size_reclaimed: lhs
7252                .accounts_data_size_reclaimed
7253                .saturating_add(rhs.accounts_data_size_reclaimed),
7254            rent_rewards: [lhs.rent_rewards, rhs.rent_rewards].concat(),
7255            time_loading_accounts_us: lhs
7256                .time_loading_accounts_us
7257                .saturating_add(rhs.time_loading_accounts_us),
7258            time_collecting_rent_us: lhs
7259                .time_collecting_rent_us
7260                .saturating_add(rhs.time_collecting_rent_us),
7261            time_storing_accounts_us: lhs
7262                .time_storing_accounts_us
7263                .saturating_add(rhs.time_storing_accounts_us),
7264            num_accounts: lhs.num_accounts.saturating_add(rhs.num_accounts),
7265        }
7266    }
7267}
7268
7269/// Struct to collect stats when scanning all accounts in `get_total_accounts_stats()`
7270#[derive(Debug, Default, Copy, Clone, Serialize)]
7271pub struct TotalAccountsStats {
7272    /// Total number of accounts
7273    pub num_accounts: usize,
7274    /// Total data size of all accounts
7275    pub data_len: usize,
7276
7277    /// Total number of executable accounts
7278    pub num_executable_accounts: usize,
7279    /// Total data size of executable accounts
7280    pub executable_data_len: usize,
7281
7282    /// Total number of rent exempt accounts
7283    pub num_rent_exempt_accounts: usize,
7284    /// Total number of rent paying accounts
7285    pub num_rent_paying_accounts: usize,
7286    /// Total number of rent paying accounts without data
7287    pub num_rent_paying_accounts_without_data: usize,
7288    /// Total amount of lamports in rent paying accounts
7289    pub lamports_in_rent_paying_accounts: u64,
7290}
7291
7292impl TotalAccountsStats {
7293    pub fn accumulate_account(
7294        &mut self,
7295        address: &Pubkey,
7296        account: &AccountSharedData,
7297        rent_collector: &RentCollector,
7298    ) {
7299        let data_len = account.data().len();
7300        self.num_accounts += 1;
7301        self.data_len += data_len;
7302
7303        if account.executable() {
7304            self.num_executable_accounts += 1;
7305            self.executable_data_len += data_len;
7306        }
7307
7308        if !rent_collector.should_collect_rent(address, account.executable())
7309            || rent_collector
7310                .get_rent_due(
7311                    account.lamports(),
7312                    account.data().len(),
7313                    account.rent_epoch(),
7314                )
7315                .is_exempt()
7316        {
7317            self.num_rent_exempt_accounts += 1;
7318        } else {
7319            self.num_rent_paying_accounts += 1;
7320            self.lamports_in_rent_paying_accounts += account.lamports();
7321            if data_len == 0 {
7322                self.num_rent_paying_accounts_without_data += 1;
7323            }
7324        }
7325    }
7326}
7327
7328impl Drop for Bank {
7329    fn drop(&mut self) {
7330        if let Some(drop_callback) = self.drop_callback.read().unwrap().0.as_ref() {
7331            drop_callback.callback(self);
7332        } else {
7333            // Default case for tests
7334            self.rc
7335                .accounts
7336                .accounts_db
7337                .purge_slot(self.slot(), self.bank_id(), false);
7338        }
7339    }
7340}
7341
7342/// utility function used for testing and benchmarking.
7343pub mod test_utils {
7344    use {
7345        super::Bank,
7346        crate::installed_scheduler_pool::BankWithScheduler,
7347        solana_sdk::{
7348            account::{ReadableAccount, WritableAccount},
7349            hash::hashv,
7350            lamports::LamportsError,
7351            pubkey::Pubkey,
7352        },
7353        solana_vote_program::vote_state::{self, BlockTimestamp, VoteStateVersions},
7354        std::sync::Arc,
7355    };
7356    pub fn goto_end_of_slot(bank: Arc<Bank>) {
7357        goto_end_of_slot_with_scheduler(&BankWithScheduler::new_without_scheduler(bank))
7358    }
7359
7360    pub fn goto_end_of_slot_with_scheduler(bank: &BankWithScheduler) {
7361        let mut tick_hash = bank.last_blockhash();
7362        loop {
7363            tick_hash = hashv(&[tick_hash.as_ref(), &[42]]);
7364            bank.register_tick(&tick_hash);
7365            if tick_hash == bank.last_blockhash() {
7366                bank.freeze();
7367                return;
7368            }
7369        }
7370    }
7371
7372    pub fn update_vote_account_timestamp(
7373        timestamp: BlockTimestamp,
7374        bank: &Bank,
7375        vote_pubkey: &Pubkey,
7376    ) {
7377        let mut vote_account = bank.get_account(vote_pubkey).unwrap_or_default();
7378        let mut vote_state = vote_state::from(&vote_account).unwrap_or_default();
7379        vote_state.last_timestamp = timestamp;
7380        let versioned = VoteStateVersions::new_current(vote_state);
7381        vote_state::to(&versioned, &mut vote_account).unwrap();
7382        bank.store_account(vote_pubkey, &vote_account);
7383    }
7384
7385    pub fn deposit(
7386        bank: &Bank,
7387        pubkey: &Pubkey,
7388        lamports: u64,
7389    ) -> std::result::Result<u64, LamportsError> {
7390        // This doesn't collect rents intentionally.
7391        // Rents should only be applied to actual TXes
7392        let mut account = bank
7393            .get_account_with_fixed_root_no_cache(pubkey)
7394            .unwrap_or_default();
7395        account.checked_add_lamports(lamports)?;
7396        bank.store_account(pubkey, &account);
7397        Ok(account.lamports())
7398    }
7399}