Skip to main content

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