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