Skip to main content

solana_runtime/
bank.rs

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