Skip to main content

solana_runtime/
bank.rs

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