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