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