Skip to main content

solana_runtime/
bank.rs

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