1pub use {
37 crate::slot_params::DEFAULT_MAX_ENTRY_BYTES_PER_SLOT,
38 partitioned_epoch_rewards::KeyedRewardsAndNumPartitions, solana_leader_schedule::SlotLeader,
39 solana_reward_info::RewardType,
40};
41use {
42 crate::{
43 account_saver::collect_accounts_to_store,
44 alpenglow_epoch_type::AlpenglowEpochType,
45 bank::{
46 entry_bytes_budget::EntryBytesBudget,
47 metrics::*,
48 partitioned_epoch_rewards::{CachedVoteAccounts, EpochRewardStatus},
49 },
50 bank_forks::BankForks,
51 block_component_processor::{
52 BlockComponentProcessor,
53 vote_reward::epoch_inflation_account_state::EpochInflationAccountState,
54 },
55 epoch_stakes::{
56 BLSPubkeyToRankMap, DeserializableVersionedEpochStakes, NodeVoteAccounts,
57 VersionedEpochStakes,
58 },
59 inflation_rewards::points::InflationPointCalculationEvent,
60 installed_scheduler_pool::{BankWithScheduler, InstalledSchedulerRwLock},
61 leader_schedule_utils::leader_schedule_from_vote_accounts,
62 rent_collector::RentCollector,
63 reward_info::RewardInfo,
64 runtime_config::RuntimeConfig,
65 slot_params::{SlotParams, SlotParamsArchive},
66 stake_account::StakeAccount,
67 stake_history::StakeHistory as CowStakeHistory,
68 stake_weighted_timestamp::{
69 MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST, MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
70 MaxAllowableDrift, calculate_stake_weighted_timestamp,
71 },
72 stakes::{
73 DelegatedStakes, DeserializableDelegationStakes, SerdeStakesToStakeFormat, Stakes,
74 StakesCache,
75 },
76 status_cache::{SlotDelta, StatusCache},
77 sysvar_account::{create_account, create_account_with_bincode, from_account},
78 transaction_batch::{OwnedOrBorrowed, TransactionBatch},
79 },
80 accounts_lt_hash::AccountsLtHashAsyncProgress,
81 agave_bls_cert_verify::cert_verify::{self, Error as CertVerifyError},
82 agave_feature_set::{self as feature_set, FeatureSet},
83 agave_precompiles::{get_precompile, get_precompiles, is_precompile},
84 agave_reserved_account_keys::ReservedAccountKeys,
85 agave_snapshots::snapshot_hash::SnapshotHash,
86 agave_votor_messages::{
87 certificate::{CertSignature, Certificate, GenesisCert},
88 migration::GENESIS_CERTIFICATE_ACCOUNT,
89 unverified_vote_message::UnverifiedCertificate,
90 wire::{WireBlockCertMessage, WireCertSignature},
91 },
92 ahash::AHashSet,
93 log::*,
94 partitioned_epoch_rewards::PartitionedRewardsCalculation,
95 rayon::ThreadPool,
96 serde::{Deserialize, Serialize},
97 solana_account::{
98 Account, AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
99 },
100 solana_accounts_db::{
101 account_locks::validate_account_locks,
102 account_storage_entry::AccountStorageEntry,
103 accounts::{AccountAddressFilter, Accounts},
104 accounts_db::{AccountsDb, AccountsDbConfig},
105 accounts_hash::AccountsLtHash,
106 accounts_index::IndexKey,
107 accounts_scan::ScanResult,
108 accounts_update_notifier_interface::AccountsUpdateNotifier,
109 ancestors::Ancestors,
110 blockhash_queue::BlockhashQueue,
111 storable_accounts::StorableAccounts,
112 utils::create_account_shared_data,
113 },
114 solana_builtins::{BUILTINS, STATELESS_BUILTINS},
115 solana_clock::{
116 BankId, Epoch, INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE, MAX_TRANSACTION_FORWARDING_DELAY,
117 Slot, SlotIndex, UnixTimestamp,
118 },
119 solana_cluster_type::ClusterType,
120 solana_compute_budget::compute_budget::ComputeBudget,
121 solana_cost_model::cost_tracker::CostTracker,
122 solana_epoch_info::EpochInfo,
123 solana_epoch_schedule::EpochSchedule,
124 solana_feature_gate_interface as feature,
125 solana_fee::FeeFeatures,
126 solana_fee_calculator::FeeRateGovernor,
127 solana_fee_structure::{FeeDetails, FeeStructure},
128 solana_genesis_config::GenesisConfig,
129 solana_hard_forks::HardForks,
130 solana_hash::Hash,
131 solana_inflation::Inflation,
132 solana_keypair::Keypair,
133 solana_lattice_hash::lt_hash::LtHash,
134 solana_measure::{measure::Measure, measure_time, measure_us},
135 solana_message::{
136 AccountKeys, SanitizedMessage, VersionedMessage, inner_instruction::InnerInstructions,
137 },
138 solana_packet::PACKET_DATA_SIZE,
139 solana_precompile_error::PrecompileError,
140 solana_program_runtime::{
141 invoke_context::BuiltinFunctionRegisterer,
142 loaded_programs::{ProgramRuntimeEnvironment, ProgramRuntimeEnvironments},
143 program_cache_entry::ProgramCacheEntry,
144 },
145 solana_pubkey::Pubkey,
146 solana_rent::Rent,
147 solana_runtime_transaction::{
148 runtime_transaction::RuntimeTransaction, transaction_meta::TransactionConfiguration,
149 transaction_with_meta::TransactionWithMeta,
150 },
151 solana_sdk_ids::{bpf_loader_upgradeable, incinerator, native_loader, system_program},
152 solana_sha256_hasher::hashv,
153 solana_signature::Signature,
154 solana_slot_hashes::SlotHashes,
155 solana_slot_history::{Check, SlotHistory},
156 solana_stake_history::{StakeHistory, sysvar as stake_history},
157 solana_stake_interface::state::Delegation,
158 solana_svm::{
159 account_loader::LoadedTransaction,
160 account_overrides::AccountOverrides,
161 transaction_balances::{BalanceCollector, SvmTokenInfo},
162 transaction_commit_result::{CommittedTransaction, TransactionCommitResult},
163 transaction_error_metrics::TransactionErrorMetrics,
164 transaction_execution_result::{
165 TransactionExecutionDetails, TransactionLoadedAccountsStats,
166 },
167 transaction_processing_result::{
168 ProcessedTransaction, TransactionProcessingResult,
169 TransactionProcessingResultExtensions,
170 },
171 transaction_processor::{
172 ExecutionRecordingConfig, TransactionBatchProcessor, TransactionLogMessages,
173 TransactionProcessingConfig, TransactionProcessingEnvironment,
174 },
175 },
176 solana_svm_callback::{AccountState, InvokeContextCallback, TransactionProcessingCallback},
177 solana_svm_timings::{ExecuteTimingType, ExecuteTimings},
178 solana_svm_transaction::svm_message::SVMMessage,
179 solana_syscalls::create_program_runtime_environment,
180 solana_system_transaction as system_transaction,
181 solana_sysvar::{self as sysvar, last_restart_slot::LastRestartSlot},
182 solana_sysvar_id::SysvarId,
183 solana_transaction::{
184 Transaction, TransactionVerificationMode,
185 sanitized::{MAX_TX_ACCOUNT_LOCKS, MessageHash, SanitizedTransaction},
186 versioned::{TransactionVersion, VersionedTransaction},
187 },
188 solana_transaction_context::{
189 transaction::TransactionReturnData, transaction_accounts::KeyedAccountSharedData,
190 },
191 solana_transaction_error::{TransactionError, TransactionResult as Result},
192 solana_vote::{
193 vote_account::{VoteAccount, VoteAccounts, VoteAccountsHashMap},
194 vote_parser,
195 },
196 solana_vote_interface::state::VoteStateV4,
197 std::{
198 collections::{HashMap, HashSet},
199 fmt,
200 ops::AddAssign,
201 path::PathBuf,
202 slice,
203 sync::{
204 Arc, LazyLock, LockResult, Mutex, OnceLock, RwLock, RwLockReadGuard, RwLockWriteGuard,
205 Weak,
206 atomic::{
207 AtomicBool, AtomicI64, AtomicU64,
208 Ordering::{AcqRel, Acquire, Relaxed},
209 },
210 },
211 time::{Duration, Instant},
212 },
213 thiserror::Error,
214 wincode::{SchemaRead, SchemaWrite},
215};
216#[cfg(feature = "dev-context-only-utils")]
217use {
218 dashmap::DashSet,
219 qualifier_attr::{field_qualifiers, qualifiers},
220 rayon::iter::{IntoParallelRefIterator, ParallelIterator},
221 solana_accounts_db::accounts_db::{
222 ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING,
223 },
224 solana_nonce as nonce,
225 solana_nonce_account::{SystemAccountKind, get_system_account_kind},
226 solana_program_runtime::sysvar_cache::SysvarCache,
227 solana_svm::program_loader::load_program_with_pubkey,
228};
229
230mod accounts_lt_hash;
231mod address_lookup_table;
232pub mod bank_hash_details;
233pub mod builtins;
234mod check_transactions;
235pub mod entry_bytes_budget;
236mod fee_distribution;
237mod metrics;
238pub(crate) mod partitioned_epoch_rewards;
239mod recent_blockhashes_account;
240mod serde_snapshot;
241mod sysvar_cache;
242pub(crate) mod tests;
243
244pub const SECONDS_PER_YEAR: f64 = 365.25 * 24.0 * 60.0 * 60.0;
245
246pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5;
247
248pub const MAX_ALPENGLOW_VOTE_ACCOUNTS: usize = 2000;
253
254pub const DEFAULT_VAT_TO_BURN_PER_EPOCH: u64 =
259 crate::slot_params::LEGACY_SLOT_PARAMS.vat_to_burn_per_epoch();
260
261static NANOSECOND_CLOCK_ACCOUNT: LazyLock<Pubkey> = LazyLock::new(|| {
264 let (pubkey, _) =
265 Pubkey::find_program_address(&[b"alpenclock"], &agave_feature_set::alpenglow::id());
266 pubkey
267});
268
269pub type BankStatusCache = StatusCache<Result<()>>;
270#[cfg_attr(
271 feature = "frozen-abi",
272 frozen_abi(digest = "2RGYA9GpP1epajQ4CxQpCHMJPnLLBoseMbAyLJhTjsGS")
273)]
274pub type BankSlotDelta = SlotDelta<Result<()>>;
275
276#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
277pub struct SquashTiming {
278 pub squash_accounts_ms: u64,
279 pub squash_accounts_cache_ms: u64,
280 pub squash_cache_ms: u64,
281}
282
283impl AddAssign for SquashTiming {
284 fn add_assign(&mut self, rhs: Self) {
285 self.squash_accounts_ms += rhs.squash_accounts_ms;
286 self.squash_accounts_cache_ms += rhs.squash_accounts_cache_ms;
287 self.squash_cache_ms += rhs.squash_cache_ms;
288 }
289}
290
291#[derive(Clone, Debug, Default, PartialEq)]
292pub struct CollectorFeeDetails {
293 transaction_fee: u64,
294 priority_fee: u64,
295}
296
297impl CollectorFeeDetails {
298 pub(crate) fn accumulate(&mut self, fee_details: &FeeDetails) {
299 self.transaction_fee = self
300 .transaction_fee
301 .saturating_add(fee_details.transaction_fee());
302 self.priority_fee = self
303 .priority_fee
304 .saturating_add(fee_details.prioritization_fee());
305 }
306
307 pub fn total_transaction_fee(&self) -> u64 {
308 self.transaction_fee.saturating_add(self.priority_fee)
309 }
310
311 pub fn total_priority_fee(&self) -> u64 {
312 self.priority_fee
313 }
314}
315
316impl From<FeeDetails> for CollectorFeeDetails {
317 fn from(fee_details: FeeDetails) -> Self {
318 CollectorFeeDetails {
319 transaction_fee: fee_details.transaction_fee(),
320 priority_fee: fee_details.prioritization_fee(),
321 }
322 }
323}
324
325#[derive(Debug)]
326pub struct BankRc {
327 pub accounts: Arc<Accounts>,
329
330 pub(crate) parent: RwLock<Option<Arc<Bank>>>,
332
333 pub(crate) bank_id_generator: Arc<AtomicU64>,
334}
335
336impl BankRc {
337 #[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
338 pub(crate) fn new(accounts: Accounts) -> Self {
339 Self {
340 accounts: Arc::new(accounts),
341 parent: RwLock::new(None),
342 bank_id_generator: Arc::new(AtomicU64::new(0)),
343 }
344 }
345}
346
347pub struct LoadAndExecuteTransactionsOutput {
348 pub processing_results: Vec<TransactionProcessingResult>,
351 pub processed_counts: ProcessedTransactionCounts,
354 pub balance_collector: Option<BalanceCollector>,
357}
358
359#[derive(Debug, PartialEq)]
360pub struct TransactionSimulationResult {
361 pub result: Result<()>,
362 pub logs: TransactionLogMessages,
363 pub post_simulation_accounts: Vec<KeyedAccountSharedData>,
364 pub units_consumed: u64,
365 pub loaded_accounts_data_size: u32,
366 pub return_data: Option<TransactionReturnData>,
367 pub inner_instructions: Option<Vec<InnerInstructions>>,
368 pub fee: Option<u64>,
369 pub pre_balances: Option<Vec<u64>>,
370 pub post_balances: Option<Vec<u64>>,
371 pub pre_token_balances: Option<Vec<SvmTokenInfo>>,
372 pub post_token_balances: Option<Vec<SvmTokenInfo>>,
373}
374
375impl TransactionSimulationResult {
376 pub fn new_error(err: TransactionError) -> Self {
377 Self {
378 fee: None,
379 inner_instructions: None,
380 loaded_accounts_data_size: 0,
381 logs: vec![],
382 post_balances: None,
383 post_simulation_accounts: vec![],
384 post_token_balances: None,
385 pre_balances: None,
386 pre_token_balances: None,
387 result: Err(err),
388 return_data: None,
389 units_consumed: 0,
390 }
391 }
392}
393
394#[derive(Clone, Debug)]
395pub struct TransactionBalancesSet {
396 pub pre_balances: TransactionBalances,
397 pub post_balances: TransactionBalances,
398}
399
400impl TransactionBalancesSet {
401 pub fn new(pre_balances: TransactionBalances, post_balances: TransactionBalances) -> Self {
402 assert_eq!(pre_balances.len(), post_balances.len());
403 Self {
404 pre_balances,
405 post_balances,
406 }
407 }
408}
409pub type TransactionBalances = Vec<Vec<u64>>;
410
411pub type PreCommitResult<'a> = Result<Option<RwLockReadGuard<'a, Hash>>>;
412
413#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Default)]
414pub enum TransactionLogCollectorFilter {
415 All,
416 AllWithVotes,
417 #[default]
418 None,
419 OnlyMentionedAddresses,
420}
421
422#[derive(Debug, Default)]
423pub struct TransactionLogCollectorConfig {
424 pub mentioned_addresses: HashSet<Pubkey>,
425 pub filter: TransactionLogCollectorFilter,
426}
427
428#[derive(Clone, Debug, PartialEq, Eq)]
429pub struct TransactionLogInfo {
430 pub signature: Signature,
431 pub result: Result<()>,
432 pub is_vote: bool,
433 pub log_messages: TransactionLogMessages,
434}
435
436#[derive(Default, Debug)]
437pub struct TransactionLogCollector {
438 pub logs: Vec<TransactionLogInfo>,
441
442 pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>,
445}
446
447impl TransactionLogCollector {
448 pub fn get_logs_for_address(
449 &self,
450 address: Option<&Pubkey>,
451 ) -> Option<Vec<TransactionLogInfo>> {
452 match address {
453 None => Some(self.logs.clone()),
454 Some(address) => self.mentioned_address_map.get(address).map(|log_indices| {
455 log_indices
456 .iter()
457 .filter_map(|i| self.logs.get(*i).cloned())
458 .collect()
459 }),
460 }
461 }
462}
463
464#[derive(Error, Debug, Serialize, Deserialize)]
465pub enum VATHealthError {
466 #[error("vote account not found")]
467 VoteAccountNotFound,
468 #[error("missing BLS pubkey")]
469 NoBLSPubkey,
470 #[error("insufficient lamports in vote account: {0} < {1}")]
471 InsufficientFundsInVoteAccount(u64, u64),
472}
473
474#[derive(Clone, Debug)]
482#[cfg_attr(
483 feature = "dev-context-only-utils",
484 field_qualifiers(
485 blockhash_queue(pub),
486 hash(pub),
487 parent_hash(pub),
488 parent_slot(pub),
489 hard_forks(pub),
490 transaction_count(pub),
491 tick_height(pub),
492 signature_count(pub),
493 capitalization(pub),
494 max_tick_height(pub),
495 hashes_per_tick(pub),
496 ticks_per_slot(pub),
497 ns_per_slot(pub),
498 genesis_creation_time(pub),
499 slots_per_year(pub),
500 slot(pub),
501 block_height(pub),
502 leader_id(pub),
503 fee_rate_governor(pub),
504 epoch_schedule(pub),
505 inflation(pub),
506 stakes(pub),
507 is_delta(pub),
508 accounts_data_len(pub),
509 versioned_epoch_stakes(pub),
510 accounts_lt_hash(pub),
511 bank_hash_stats(pub),
512 block_id(pub),
513 )
514)]
515pub struct BankFieldsToDeserialize {
516 pub(crate) blockhash_queue: BlockhashQueue,
517 pub(crate) hash: Hash,
518 pub(crate) parent_hash: Hash,
519 pub(crate) parent_slot: Slot,
520 pub(crate) hard_forks: HardForks,
521 pub(crate) transaction_count: u64,
522 pub(crate) tick_height: u64,
523 pub(crate) signature_count: u64,
524 pub(crate) capitalization: u64,
525 pub(crate) max_tick_height: u64,
526 pub(crate) hashes_per_tick: Option<u64>,
527 pub(crate) ticks_per_slot: u64,
528 pub(crate) ns_per_slot: u128,
529 pub(crate) genesis_creation_time: UnixTimestamp,
530 pub(crate) slots_per_year: f64,
531 pub(crate) slot: Slot,
532 pub(crate) block_height: u64,
533 pub(crate) leader_id: Pubkey,
534 pub(crate) fee_rate_governor: FeeRateGovernor,
535 pub(crate) epoch_schedule: EpochSchedule,
536 pub(crate) inflation: Inflation,
537 pub(crate) stakes: DeserializableDelegationStakes,
538 pub(crate) versioned_epoch_stakes: Vec<(Epoch, DeserializableVersionedEpochStakes)>,
541 pub(crate) is_delta: bool,
542 pub(crate) accounts_data_len: u64,
543 pub(crate) accounts_lt_hash: AccountsLtHash,
544 pub(crate) bank_hash_stats: BankHashStats,
545 pub(crate) block_id: Option<Hash>, }
547
548#[cfg(feature = "dev-context-only-utils")]
549impl Default for BankFieldsToDeserialize {
550 fn default() -> Self {
551 Self {
552 blockhash_queue: BlockhashQueue::default(),
553 hash: Hash::default(),
554 parent_hash: Hash::default(),
555 parent_slot: Slot::default(),
556 hard_forks: HardForks::default(),
557 transaction_count: u64::default(),
558 tick_height: u64::default(),
559 signature_count: u64::default(),
560 capitalization: u64::default(),
561 max_tick_height: u64::default(),
562 hashes_per_tick: Option::<u64>::default(),
563 ticks_per_slot: u64::default(),
564 ns_per_slot: u128::default(),
565 genesis_creation_time: UnixTimestamp::default(),
566 slots_per_year: f64::default(),
567 slot: Slot::default(),
568 block_height: u64::default(),
569 leader_id: Pubkey::default(),
570 fee_rate_governor: FeeRateGovernor::default(),
571 epoch_schedule: EpochSchedule::default(),
572 inflation: Inflation::default(),
573 stakes: DeserializableDelegationStakes {
574 vote_accounts: VoteAccounts::default(),
575 stake_delegations: Vec::default(),
576 unused: u64::default(),
577 epoch: Epoch::default(),
578 stake_history: CowStakeHistory::default(),
579 },
580 versioned_epoch_stakes: Vec::default(),
581 is_delta: bool::default(),
582 accounts_data_len: u64::default(),
583 accounts_lt_hash: AccountsLtHash(LtHash::identity()),
584 bank_hash_stats: BankHashStats::default(),
585 block_id: Option::<Hash>::default(),
586 }
587 }
588}
589
590#[derive(Debug)]
599pub struct BankFieldsToSerialize {
600 pub blockhash_queue: BlockhashQueue,
601 pub hash: Hash,
602 pub parent_hash: Hash,
603 pub parent_slot: Slot,
604 pub hard_forks: HardForks,
605 pub transaction_count: u64,
606 pub tick_height: u64,
607 pub signature_count: u64,
608 pub capitalization: u64,
609 pub max_tick_height: u64,
610 pub hashes_per_tick: Option<u64>,
611 pub ticks_per_slot: u64,
612 pub ns_per_slot: u128,
613 pub genesis_creation_time: UnixTimestamp,
614 pub slots_per_year: f64,
615 pub slot: Slot,
616 pub block_height: u64,
617 pub leader_id: Pubkey,
618 pub fee_rate_governor: FeeRateGovernor,
619 pub epoch_schedule: EpochSchedule,
620 pub inflation: Inflation,
621 pub stakes: Stakes<StakeAccount<Delegation>>,
622 pub is_delta: bool,
623 pub accounts_data_len: u64,
624 pub versioned_epoch_stakes: HashMap<u64, VersionedEpochStakes>,
625 pub accounts_lt_hash: AccountsLtHash,
626 pub block_id: Hash,
627}
628
629#[cfg(feature = "dev-context-only-utils")]
631impl PartialEq for Bank {
632 fn eq(&self, other: &Self) -> bool {
633 if std::ptr::eq(self, other) {
634 return true;
635 }
636 #[rustfmt::skip]
638 let Self {
639 rc: _,
640 status_cache: _,
641 store_transaction_signatures_in_status_cache,
642 blockhash_queue,
643 max_processing_age,
644 partitioned_rewards_stake_account_stores_per_block,
645 ancestors: _,
646 hash,
647 parent_hash,
648 parent_slot,
649 hard_forks,
650 transaction_count,
651 non_vote_transaction_count_since_restart: _,
652 transaction_error_count: _,
653 transaction_entries_count: _,
654 transactions_per_entry_max: _,
655 entry_bytes_consumed: _,
656 tick_height,
657 signature_count,
658 capitalization,
659 max_tick_height,
660 hashes_per_tick,
661 ticks_per_slot,
662 ns_per_slot,
663 genesis_creation_time,
664 slots_per_year,
665 slot_params: _,
666 slot,
667 bank_id: _,
668 epoch,
669 block_height,
670 leader,
671 fee_rate_governor,
672 rent_collector,
673 epoch_schedule,
674 inflation,
675 stakes_cache,
676 epoch_stakes,
677 is_delta,
678 #[cfg(feature = "dev-context-only-utils")]
679 hash_overrides,
680 accounts_lt_hash,
681 is_alpenglow,
682 rewards: _,
684 cluster_type: _,
685 transaction_debug_keys: _,
686 transaction_log_collector_config: _,
687 transaction_log_collector: _,
688 feature_set: _,
689 reserved_account_keys: _,
690 drop_callback: _,
691 freeze_started: _,
692 vote_only_bank: _,
693 cost_tracker: _,
694 accounts_data_size_initial: _,
695 accounts_data_size_delta_on_chain: _,
696 accounts_data_size_delta_off_chain: _,
697 epoch_reward_status: _,
698 transaction_processor: _,
699 collector_fee_details: _,
700 compute_budget: _,
701 transaction_account_lock_limit: _,
702 fee_structure: _,
703 accounts_lt_hash_async_progress: _,
704 block_id,
705 expected_bank_hash: _,
706 bank_hash_stats: _,
707 epoch_rewards_calculation_cache: _,
708 block_component_processor: _,
709 } = self;
713 *store_transaction_signatures_in_status_cache
714 == other.store_transaction_signatures_in_status_cache
715 && *blockhash_queue.read().unwrap() == *other.blockhash_queue.read().unwrap()
716 && *max_processing_age == other.max_processing_age
717 && *partitioned_rewards_stake_account_stores_per_block
718 == other.partitioned_rewards_stake_account_stores_per_block
719 && *hash.read().unwrap() == *other.hash.read().unwrap()
720 && parent_hash == &other.parent_hash
721 && parent_slot == &other.parent_slot
722 && *hard_forks.read().unwrap() == *other.hard_forks.read().unwrap()
723 && transaction_count.load(Relaxed) == other.transaction_count.load(Relaxed)
724 && tick_height.load(Relaxed) == other.tick_height.load(Relaxed)
725 && signature_count.load(Relaxed) == other.signature_count.load(Relaxed)
726 && capitalization.load(Relaxed) == other.capitalization.load(Relaxed)
727 && max_tick_height == &other.max_tick_height
728 && *hashes_per_tick.read().unwrap() == *other.hashes_per_tick.read().unwrap()
729 && ticks_per_slot == &other.ticks_per_slot
730 && ns_per_slot == &other.ns_per_slot
731 && genesis_creation_time == &other.genesis_creation_time
732 && slots_per_year == &other.slots_per_year
733 && slot == &other.slot
734 && epoch == &other.epoch
735 && block_height == &other.block_height
736 && leader == &other.leader
737 && fee_rate_governor == &other.fee_rate_governor
738 && rent_collector == &other.rent_collector
739 && epoch_schedule == &other.epoch_schedule
740 && *inflation.read().unwrap() == *other.inflation.read().unwrap()
741 && *stakes_cache.stakes() == *other.stakes_cache.stakes()
742 && epoch_stakes == &other.epoch_stakes
743 && is_delta.load(Relaxed) == other.is_delta.load(Relaxed)
744 && (Arc::ptr_eq(hash_overrides, &other.hash_overrides) ||
747 *hash_overrides.lock().unwrap() == *other.hash_overrides.lock().unwrap())
748 && *accounts_lt_hash.lock().unwrap() == *other.accounts_lt_hash.lock().unwrap()
749 && *block_id.read().unwrap() == *other.block_id.read().unwrap()
750 && is_alpenglow.load(Relaxed) == other.is_alpenglow()
751 }
752}
753
754#[cfg(feature = "dev-context-only-utils")]
755impl BankFieldsToSerialize {
756 pub fn default_for_tests() -> Self {
759 Self {
760 blockhash_queue: BlockhashQueue::default(),
761 hash: Hash::default(),
762 parent_hash: Hash::default(),
763 parent_slot: Slot::default(),
764 hard_forks: HardForks::default(),
765 transaction_count: u64::default(),
766 tick_height: u64::default(),
767 signature_count: u64::default(),
768 capitalization: u64::default(),
769 max_tick_height: u64::default(),
770 hashes_per_tick: Option::default(),
771 ticks_per_slot: u64::default(),
772 ns_per_slot: u128::default(),
773 genesis_creation_time: UnixTimestamp::default(),
774 slots_per_year: f64::default(),
775 slot: Slot::default(),
776 block_height: u64::default(),
777 leader_id: Pubkey::default(),
778 fee_rate_governor: FeeRateGovernor::default(),
779 epoch_schedule: EpochSchedule::default(),
780 inflation: Inflation::default(),
781 stakes: Stakes::<StakeAccount<Delegation>>::default(),
782 is_delta: bool::default(),
783 accounts_data_len: u64::default(),
784 versioned_epoch_stakes: HashMap::default(),
785 accounts_lt_hash: AccountsLtHash(LtHash([0x7E57; LtHash::NUM_ELEMENTS])),
786 block_id: Hash::default(),
787 }
788 }
789}
790
791#[derive(Debug)]
792pub enum RewardCalculationEvent<'a, 'b> {
793 Staking(&'a Pubkey, &'b InflationPointCalculationEvent),
794}
795pub trait RewardCalcTracer: Fn(&RewardCalculationEvent) + Send + Sync {}
799
800impl<T: Fn(&RewardCalculationEvent) + Send + Sync> RewardCalcTracer for T {}
801
802fn null_tracer() -> Option<impl RewardCalcTracer> {
803 None::<fn(&RewardCalculationEvent)>
804}
805
806pub trait DropCallback: fmt::Debug {
807 fn callback(&self, b: &Bank);
808 fn clone_box(&self) -> Box<dyn DropCallback + Send + Sync>;
809}
810
811#[derive(Debug, Default)]
812pub struct OptionalDropCallback(Option<Box<dyn DropCallback + Send + Sync>>);
813
814#[derive(Default, Debug, Clone, PartialEq)]
815#[cfg(feature = "dev-context-only-utils")]
816pub struct HashOverrides {
817 hashes: HashMap<Slot, HashOverride>,
818}
819
820#[cfg(feature = "dev-context-only-utils")]
821impl HashOverrides {
822 fn get_hash_override(&self, slot: Slot) -> Option<&HashOverride> {
823 self.hashes.get(&slot)
824 }
825
826 fn get_blockhash_override(&self, slot: Slot) -> Option<&Hash> {
827 self.get_hash_override(slot)
828 .map(|hash_override| &hash_override.blockhash)
829 }
830
831 fn get_bank_hash_override(&self, slot: Slot) -> Option<&Hash> {
832 self.get_hash_override(slot)
833 .map(|hash_override| &hash_override.bank_hash)
834 }
835
836 pub fn add_override(&mut self, slot: Slot, blockhash: Hash, bank_hash: Hash) {
837 let is_new = self
838 .hashes
839 .insert(
840 slot,
841 HashOverride {
842 blockhash,
843 bank_hash,
844 },
845 )
846 .is_none();
847 assert!(is_new);
848 }
849}
850
851#[derive(Debug, Clone, PartialEq)]
852#[cfg(feature = "dev-context-only-utils")]
853struct HashOverride {
854 blockhash: Hash,
855 bank_hash: Hash,
856}
857
858pub struct Bank {
860 pub rc: BankRc,
862
863 pub status_cache: Arc<RwLock<BankStatusCache>>,
865
866 store_transaction_signatures_in_status_cache: bool,
868
869 blockhash_queue: RwLock<BlockhashQueue>,
871
872 max_processing_age: usize,
874
875 partitioned_rewards_stake_account_stores_per_block: u64,
877
878 pub ancestors: Ancestors,
880
881 hash: RwLock<Hash>,
883
884 parent_hash: Hash,
886
887 parent_slot: Slot,
889
890 hard_forks: Arc<RwLock<HardForks>>,
892
893 transaction_count: AtomicU64,
895
896 non_vote_transaction_count_since_restart: AtomicU64,
901
902 transaction_error_count: AtomicU64,
904
905 transaction_entries_count: AtomicU64,
907
908 transactions_per_entry_max: AtomicU64,
910
911 entry_bytes_consumed: EntryBytesBudget,
913
914 tick_height: AtomicU64,
916
917 signature_count: AtomicU64,
919
920 capitalization: AtomicU64,
922
923 max_tick_height: u64,
925
926 hashes_per_tick: RwLock<Option<u64>>,
928
929 ticks_per_slot: u64,
931
932 pub ns_per_slot: u128,
934
935 genesis_creation_time: UnixTimestamp,
937
938 slots_per_year: f64,
940
941 slot_params: SlotParamsArchive,
943
944 slot: Slot,
946
947 bank_id: BankId,
948
949 epoch: Epoch,
951
952 block_height: u64,
954
955 leader: SlotLeader,
957
958 pub(crate) fee_rate_governor: FeeRateGovernor,
960
961 rent_collector: RentCollector,
963
964 pub(crate) epoch_schedule: EpochSchedule,
966
967 inflation: Arc<RwLock<Inflation>>,
969
970 stakes_cache: StakesCache,
972
973 epoch_stakes: HashMap<Epoch, VersionedEpochStakes>,
976
977 is_delta: AtomicBool,
980
981 pub rewards: RwLock<Vec<(Pubkey, RewardInfo)>>,
983
984 pub cluster_type: Option<ClusterType>,
985
986 transaction_debug_keys: Option<Arc<HashSet<Pubkey>>>,
987
988 pub transaction_log_collector_config: Arc<RwLock<TransactionLogCollectorConfig>>,
990
991 pub transaction_log_collector: Arc<RwLock<TransactionLogCollector>>,
994
995 pub feature_set: Arc<FeatureSet>,
996
997 reserved_account_keys: Arc<ReservedAccountKeys>,
999
1000 pub drop_callback: RwLock<OptionalDropCallback>,
1002
1003 pub freeze_started: AtomicBool,
1004
1005 vote_only_bank: bool,
1006
1007 cost_tracker: RwLock<CostTracker>,
1008
1009 accounts_data_size_initial: u64,
1011 accounts_data_size_delta_on_chain: AtomicI64,
1013 accounts_data_size_delta_off_chain: AtomicI64,
1015
1016 epoch_reward_status: EpochRewardStatus,
1017
1018 transaction_processor: TransactionBatchProcessor<BankForks>,
1019
1020 collector_fee_details: RwLock<CollectorFeeDetails>,
1022
1023 compute_budget: Option<ComputeBudget>,
1025
1026 transaction_account_lock_limit: Option<usize>,
1028
1029 fee_structure: FeeStructure,
1031
1032 #[cfg(feature = "dev-context-only-utils")]
1035 hash_overrides: Arc<Mutex<HashOverrides>>,
1036
1037 accounts_lt_hash: Mutex<AccountsLtHash>,
1041
1042 accounts_lt_hash_async_progress: Arc<AccountsLtHashAsyncProgress>,
1044
1045 block_id: RwLock<Option<Hash>>,
1049
1050 expected_bank_hash: RwLock<Option<Hash>>,
1053
1054 bank_hash_stats: AtomicBankHashStats,
1056
1057 epoch_rewards_calculation_cache: Arc<Mutex<HashMap<Hash, Arc<PartitionedRewardsCalculation>>>>,
1061
1062 pub block_component_processor: RwLock<BlockComponentProcessor>,
1066
1067 is_alpenglow: AtomicBool,
1069}
1070
1071#[derive(Debug, Default)]
1072pub struct NewBankOptions {
1073 pub vote_only_bank: bool,
1074}
1075
1076#[cfg(feature = "dev-context-only-utils")]
1077#[derive(Debug)]
1078pub struct BankTestConfig {
1079 pub accounts_db_config: AccountsDbConfig,
1080}
1081
1082#[cfg(feature = "dev-context-only-utils")]
1083impl Default for BankTestConfig {
1084 fn default() -> Self {
1085 Self {
1086 accounts_db_config: ACCOUNTS_DB_CONFIG_FOR_TESTING,
1087 }
1088 }
1089}
1090
1091#[derive(Debug, Default, PartialEq)]
1092pub struct ProcessedTransactionCounts {
1093 pub processed_transactions_count: u64,
1094 pub processed_non_vote_transactions_count: u64,
1095 pub processed_with_successful_result_count: u64,
1096 pub signature_count: u64,
1097}
1098
1099#[repr(C)]
1102#[cfg_attr(feature = "frozen-abi", derive(AbiExample, StableAbi, StableAbiSample))]
1103#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, SchemaRead, SchemaWrite)]
1104pub struct BankHashStats {
1105 pub num_updated_accounts: u64,
1106 pub num_removed_accounts: u64,
1107 pub num_lamports_stored: u64,
1108 pub total_data_len: u64,
1109 pub num_executable_accounts: u64,
1110}
1111
1112impl BankHashStats {
1113 pub fn update<T: ReadableAccount>(&mut self, account: &T) {
1114 if account.lamports() == 0 {
1115 self.num_removed_accounts += 1;
1116 } else {
1117 self.num_updated_accounts += 1;
1118 }
1119 self.total_data_len = self
1120 .total_data_len
1121 .wrapping_add(account.data().len() as u64);
1122 if account.executable() {
1123 self.num_executable_accounts += 1;
1124 }
1125 self.num_lamports_stored = self.num_lamports_stored.wrapping_add(account.lamports());
1126 }
1127 pub fn accumulate(&mut self, other: &BankHashStats) {
1128 self.num_updated_accounts += other.num_updated_accounts;
1129 self.num_removed_accounts += other.num_removed_accounts;
1130 self.total_data_len = self.total_data_len.wrapping_add(other.total_data_len);
1131 self.num_lamports_stored = self
1132 .num_lamports_stored
1133 .wrapping_add(other.num_lamports_stored);
1134 self.num_executable_accounts += other.num_executable_accounts;
1135 }
1136}
1137
1138#[derive(Debug, Default)]
1139pub struct AtomicBankHashStats {
1140 pub num_updated_accounts: AtomicU64,
1141 pub num_removed_accounts: AtomicU64,
1142 pub num_lamports_stored: AtomicU64,
1143 pub total_data_len: AtomicU64,
1144 pub num_executable_accounts: AtomicU64,
1145}
1146
1147impl AtomicBankHashStats {
1148 pub fn new(stat: &BankHashStats) -> Self {
1149 AtomicBankHashStats {
1150 num_updated_accounts: AtomicU64::new(stat.num_updated_accounts),
1151 num_removed_accounts: AtomicU64::new(stat.num_removed_accounts),
1152 num_lamports_stored: AtomicU64::new(stat.num_lamports_stored),
1153 total_data_len: AtomicU64::new(stat.total_data_len),
1154 num_executable_accounts: AtomicU64::new(stat.num_executable_accounts),
1155 }
1156 }
1157
1158 pub fn accumulate(&self, other: &BankHashStats) {
1159 self.num_updated_accounts
1160 .fetch_add(other.num_updated_accounts, Relaxed);
1161 self.num_removed_accounts
1162 .fetch_add(other.num_removed_accounts, Relaxed);
1163 self.total_data_len.fetch_add(other.total_data_len, Relaxed);
1164 self.num_lamports_stored
1165 .fetch_add(other.num_lamports_stored, Relaxed);
1166 self.num_executable_accounts
1167 .fetch_add(other.num_executable_accounts, Relaxed);
1168 }
1169
1170 pub fn load(&self) -> BankHashStats {
1171 BankHashStats {
1172 num_updated_accounts: self.num_updated_accounts.load(Relaxed),
1173 num_removed_accounts: self.num_removed_accounts.load(Relaxed),
1174 num_lamports_stored: self.num_lamports_stored.load(Relaxed),
1175 total_data_len: self.total_data_len.load(Relaxed),
1176 num_executable_accounts: self.num_executable_accounts.load(Relaxed),
1177 }
1178 }
1179}
1180
1181struct NewEpochBundle {
1182 stake_history: CowStakeHistory,
1183 unfiltered_distribution_vote_accounts: VoteAccounts,
1186 delegated_stakes: DelegatedStakes,
1188 filtered_distribution_vote_accounts: VoteAccounts,
1191 rewards_calculation: Arc<PartitionedRewardsCalculation>,
1192 calculate_activated_stake_time_us: u64,
1193 update_rewards_with_thread_pool_time_us: u64,
1194}
1195
1196impl Bank {
1197 fn default_with_accounts(accounts: Accounts) -> Self {
1198 let partitioned_rewards_stake_account_stores_per_block = accounts
1199 .accounts_db
1200 .partitioned_epoch_rewards_config
1201 .stake_account_stores_per_block;
1202 let mut bank = Self {
1203 rc: BankRc::new(accounts),
1204 status_cache: Arc::<RwLock<BankStatusCache>>::default(),
1205 store_transaction_signatures_in_status_cache: !RuntimeConfig::default()
1206 .skip_transaction_signatures_in_status_cache,
1207 blockhash_queue: RwLock::<BlockhashQueue>::default(),
1208 max_processing_age: MAX_PROCESSING_AGE,
1209 partitioned_rewards_stake_account_stores_per_block,
1210 ancestors: Ancestors::default(),
1211 hash: RwLock::<Hash>::default(),
1212 parent_hash: Hash::default(),
1213 parent_slot: Slot::default(),
1214 hard_forks: Arc::<RwLock<HardForks>>::default(),
1215 transaction_count: AtomicU64::default(),
1216 non_vote_transaction_count_since_restart: AtomicU64::default(),
1217 transaction_error_count: AtomicU64::default(),
1218 transaction_entries_count: AtomicU64::default(),
1219 transactions_per_entry_max: AtomicU64::default(),
1220 entry_bytes_consumed: EntryBytesBudget::new(DEFAULT_MAX_ENTRY_BYTES_PER_SLOT),
1221 tick_height: AtomicU64::default(),
1222 signature_count: AtomicU64::default(),
1223 capitalization: AtomicU64::default(),
1224 max_tick_height: u64::default(),
1225 hashes_per_tick: RwLock::default(),
1226 ticks_per_slot: u64::default(),
1227 ns_per_slot: u128::default(),
1228 genesis_creation_time: UnixTimestamp::default(),
1229 slots_per_year: f64::default(),
1230 slot_params: SlotParamsArchive::default(),
1231 slot: Slot::default(),
1232 bank_id: BankId::default(),
1233 epoch: Epoch::default(),
1234 block_height: u64::default(),
1235 leader: SlotLeader::default(),
1236 fee_rate_governor: FeeRateGovernor::default(),
1237 rent_collector: RentCollector::default(),
1238 epoch_schedule: EpochSchedule::default(),
1239 inflation: Arc::<RwLock<Inflation>>::default(),
1240 stakes_cache: StakesCache::default(),
1241 epoch_stakes: HashMap::<Epoch, VersionedEpochStakes>::default(),
1242 is_delta: AtomicBool::default(),
1243 rewards: RwLock::<Vec<(Pubkey, RewardInfo)>>::default(),
1244 cluster_type: Option::<ClusterType>::default(),
1245 transaction_debug_keys: Option::<Arc<HashSet<Pubkey>>>::default(),
1246 transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
1247 ),
1248 transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
1249 feature_set: Arc::<FeatureSet>::default(),
1250 reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
1251 drop_callback: RwLock::new(OptionalDropCallback(None)),
1252 freeze_started: AtomicBool::default(),
1253 vote_only_bank: false,
1254 cost_tracker: RwLock::<CostTracker>::default(),
1255 accounts_data_size_initial: 0,
1256 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1257 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1258 epoch_reward_status: EpochRewardStatus::default(),
1259 transaction_processor: TransactionBatchProcessor::default(),
1260 collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1261 compute_budget: None,
1262 transaction_account_lock_limit: None,
1263 fee_structure: FeeStructure::default(),
1264 #[cfg(feature = "dev-context-only-utils")]
1265 hash_overrides: Arc::new(Mutex::new(HashOverrides::default())),
1266 accounts_lt_hash: Mutex::new(AccountsLtHash(LtHash::identity())),
1267 accounts_lt_hash_async_progress: Arc::new(AccountsLtHashAsyncProgress::new()),
1268 block_id: RwLock::new(None),
1269 expected_bank_hash: RwLock::new(None),
1270 bank_hash_stats: AtomicBankHashStats::default(),
1271 epoch_rewards_calculation_cache: Arc::new(Mutex::new(HashMap::default())),
1272 block_component_processor: RwLock::new(BlockComponentProcessor::default()),
1273 is_alpenglow: AtomicBool::new(false),
1274 };
1275
1276 bank.transaction_processor =
1277 TransactionBatchProcessor::new_uninitialized(bank.slot, bank.epoch);
1278
1279 bank.accounts_data_size_initial = bank.calculate_accounts_data_size().unwrap();
1280
1281 bank
1282 }
1283
1284 #[expect(clippy::too_many_arguments)]
1285 pub fn new_from_genesis(
1286 genesis_config: &GenesisConfig,
1287 runtime_config: Arc<RuntimeConfig>,
1288 paths: Vec<PathBuf>,
1289 debug_keys: Option<Arc<HashSet<Pubkey>>>,
1290 accounts_db_config: AccountsDbConfig,
1291 accounts_update_notifier: Option<AccountsUpdateNotifier>,
1292 #[cfg_attr(not(feature = "dev-context-only-utils"), expect(unused))]
1293 leader_for_tests: Option<SlotLeader>,
1294 exit: Arc<AtomicBool>,
1295 #[cfg_attr(not(feature = "dev-context-only-utils"), expect(unused))] genesis_hash: Option<
1296 Hash,
1297 >,
1298 #[cfg_attr(not(feature = "dev-context-only-utils"), expect(unused))] feature_set: Option<
1299 FeatureSet,
1300 >,
1301 ) -> Self {
1302 let _rewards_calculation_thread_pool = rewards_calculation_thread_pool();
1305 let accounts_db =
1306 AccountsDb::new_with_config(paths, accounts_db_config, accounts_update_notifier, exit);
1307 let accounts = Accounts::new(Arc::new(accounts_db));
1308 let mut bank = Self::default_with_accounts(accounts);
1309 bank.ancestors = Ancestors::from(vec![bank.slot()]);
1310 bank.compute_budget = runtime_config.compute_budget;
1311 bank.store_transaction_signatures_in_status_cache =
1312 !runtime_config.skip_transaction_signatures_in_status_cache;
1313 if let Some(compute_budget) = &bank.compute_budget {
1314 bank.transaction_processor
1315 .set_execution_cost(compute_budget.to_cost());
1316 }
1317 bank.transaction_account_lock_limit = runtime_config.transaction_account_lock_limit;
1318 bank.transaction_debug_keys = debug_keys;
1319 bank.cluster_type = Some(genesis_config.cluster_type);
1320
1321 #[cfg(feature = "dev-context-only-utils")]
1322 {
1323 bank.feature_set = Arc::new(feature_set.unwrap_or_default());
1324 }
1325
1326 #[cfg(not(feature = "dev-context-only-utils"))]
1327 bank.process_genesis_config(genesis_config);
1328 #[cfg(feature = "dev-context-only-utils")]
1329 bank.process_genesis_config(genesis_config, leader_for_tests, genesis_hash);
1330
1331 bank.compute_and_apply_genesis_features();
1332
1333 {
1336 let stakes = bank.get_top_epoch_stakes();
1337 let stakes = SerdeStakesToStakeFormat::from(stakes);
1338 for epoch in 0..=bank.get_leader_schedule_epoch(bank.slot) {
1339 bank.epoch_stakes
1340 .insert(epoch, VersionedEpochStakes::new(stakes.clone(), epoch));
1341 }
1342 bank.update_stake_history(None);
1343 }
1344 bank.update_clock(None);
1345 bank.update_rent();
1346 bank.update_epoch_schedule();
1347 bank.update_recent_blockhashes();
1348 bank.update_last_restart_slot();
1349 bank.transaction_processor
1350 .fill_missing_sysvar_cache_entries(&bank);
1351 if bank.get_alpenglow_genesis_certificate().is_some() {
1352 bank.set_is_alpenglow();
1353 }
1354 bank
1355 }
1356
1357 pub fn new_from_parent(parent: Arc<Bank>, leader: SlotLeader, slot: Slot) -> Self {
1359 Self::_new_from_parent(
1360 parent,
1361 leader,
1362 slot,
1363 null_tracer(),
1364 NewBankOptions::default(),
1365 )
1366 }
1367
1368 pub fn new_from_parent_with_options(
1369 parent: Arc<Bank>,
1370 leader: SlotLeader,
1371 slot: Slot,
1372 new_bank_options: NewBankOptions,
1373 ) -> Self {
1374 Self::_new_from_parent(parent, leader, slot, null_tracer(), new_bank_options)
1375 }
1376
1377 pub fn new_from_parent_with_tracer(
1378 parent: Arc<Bank>,
1379 leader: SlotLeader,
1380 slot: Slot,
1381 reward_calc_tracer: impl RewardCalcTracer,
1382 ) -> Self {
1383 Self::_new_from_parent(
1384 parent,
1385 leader,
1386 slot,
1387 Some(reward_calc_tracer),
1388 NewBankOptions::default(),
1389 )
1390 }
1391
1392 fn get_rent_collector_from(rent_collector: &RentCollector, epoch: Epoch) -> RentCollector {
1393 rent_collector.clone_with_epoch(epoch)
1394 }
1395
1396 fn _new_from_parent(
1397 parent: Arc<Bank>,
1398 leader: SlotLeader,
1399 slot: Slot,
1400 reward_calc_tracer: Option<impl RewardCalcTracer>,
1401 new_bank_options: NewBankOptions,
1402 ) -> Self {
1403 let mut time = Measure::start("bank::new_from_parent");
1404 let NewBankOptions { vote_only_bank } = new_bank_options;
1405
1406 parent.freeze();
1407 assert_ne!(slot, parent.slot());
1408
1409 let epoch_schedule = parent.epoch_schedule().clone();
1410 let epoch = epoch_schedule.get_epoch(slot);
1411
1412 let (rc, bank_rc_creation_time_us) = measure_us!({
1413 let accounts_db = Arc::clone(&parent.rc.accounts.accounts_db);
1414 BankRc {
1415 accounts: Arc::new(Accounts::new(accounts_db)),
1416 parent: RwLock::new(Some(Arc::clone(&parent))),
1417 bank_id_generator: Arc::clone(&parent.rc.bank_id_generator),
1418 }
1419 });
1420
1421 let (status_cache, status_cache_time_us) = measure_us!(Arc::clone(&parent.status_cache));
1422
1423 let (fee_rate_governor, fee_components_time_us) = measure_us!(
1424 FeeRateGovernor::new_derived(&parent.fee_rate_governor, parent.signature_count())
1425 );
1426
1427 let bank_id = rc.bank_id_generator.fetch_add(1, Relaxed) + 1;
1428 let (blockhash_queue, blockhash_queue_time_us) =
1429 measure_us!(RwLock::new(parent.blockhash_queue.read().unwrap().clone()));
1430
1431 let (stakes_cache, stakes_cache_time_us) =
1432 measure_us!(StakesCache::new(parent.stakes_cache.stakes().clone()));
1433
1434 let (epoch_stakes, epoch_stakes_time_us) = measure_us!(parent.epoch_stakes.clone());
1435
1436 let (transaction_processor, builtin_program_ids_time_us) = measure_us!(
1437 TransactionBatchProcessor::new_from(&parent.transaction_processor, slot, epoch)
1438 );
1439
1440 let (transaction_debug_keys, transaction_debug_keys_time_us) =
1441 measure_us!(parent.transaction_debug_keys.clone());
1442
1443 let (transaction_log_collector_config, transaction_log_collector_config_time_us) =
1444 measure_us!(parent.transaction_log_collector_config.clone());
1445
1446 let (feature_set, feature_set_time_us) = measure_us!(parent.feature_set.clone());
1447
1448 let accounts_data_size_initial = parent.load_accounts_data_size();
1449 let mut new = Self {
1450 rc,
1451 status_cache,
1452 store_transaction_signatures_in_status_cache: parent
1453 .store_transaction_signatures_in_status_cache,
1454 slot,
1455 bank_id,
1456 epoch,
1457 blockhash_queue,
1458 max_processing_age: parent.max_processing_age,
1459 partitioned_rewards_stake_account_stores_per_block: parent
1460 .partitioned_rewards_stake_account_stores_per_block,
1461 hashes_per_tick: RwLock::new(parent.hashes_per_tick()),
1463 ticks_per_slot: parent.ticks_per_slot,
1464 ns_per_slot: parent.ns_per_slot,
1465 genesis_creation_time: parent.genesis_creation_time,
1466 slots_per_year: parent.slots_per_year,
1467 slot_params: parent.slot_params.clone(),
1468 epoch_schedule,
1469 rent_collector: Self::get_rent_collector_from(&parent.rent_collector, epoch),
1470 max_tick_height: slot
1471 .checked_add(1)
1472 .expect("max tick height addition overflowed")
1473 .checked_mul(parent.ticks_per_slot)
1474 .expect("max tick height multiplication overflowed"),
1475 block_height: parent
1476 .block_height
1477 .checked_add(1)
1478 .expect("block height addition overflowed"),
1479 fee_rate_governor,
1480 capitalization: AtomicU64::new(parent.capitalization()),
1481 vote_only_bank,
1482 inflation: parent.inflation.clone(),
1483 transaction_count: AtomicU64::new(parent.transaction_count()),
1484 non_vote_transaction_count_since_restart: AtomicU64::new(
1485 parent.non_vote_transaction_count_since_restart(),
1486 ),
1487 transaction_error_count: AtomicU64::new(0),
1488 transaction_entries_count: AtomicU64::new(0),
1489 transactions_per_entry_max: AtomicU64::new(0),
1490 entry_bytes_consumed: EntryBytesBudget::new(parent.entry_bytes_budget().slot_limit()),
1491 stakes_cache,
1493 epoch_stakes,
1494 parent_hash: parent.hash(),
1495 parent_slot: parent.slot(),
1496 leader,
1497 ancestors: Ancestors::default(),
1498 hash: RwLock::new(Hash::default()),
1499 is_delta: AtomicBool::new(false),
1500 tick_height: AtomicU64::new(parent.tick_height.load(Relaxed)),
1501 signature_count: AtomicU64::new(0),
1502 hard_forks: parent.hard_forks.clone(),
1503 rewards: RwLock::new(vec![]),
1504 cluster_type: parent.cluster_type,
1505 transaction_debug_keys,
1506 transaction_log_collector_config,
1507 transaction_log_collector: Arc::new(RwLock::new(TransactionLogCollector::default())),
1508 feature_set: Arc::clone(&feature_set),
1509 reserved_account_keys: parent.reserved_account_keys.clone(),
1510 drop_callback: RwLock::new(OptionalDropCallback(
1511 parent
1512 .drop_callback
1513 .read()
1514 .unwrap()
1515 .0
1516 .as_ref()
1517 .map(|drop_callback| drop_callback.clone_box()),
1518 )),
1519 freeze_started: AtomicBool::new(false),
1520 cost_tracker: RwLock::new(parent.read_cost_tracker().unwrap().new_from_parent_limits()),
1521 accounts_data_size_initial,
1522 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1523 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1524 epoch_reward_status: parent.epoch_reward_status.clone(),
1525 transaction_processor,
1526 collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1527 compute_budget: parent.compute_budget,
1528 transaction_account_lock_limit: parent.transaction_account_lock_limit,
1529 fee_structure: parent.fee_structure.clone(),
1530 #[cfg(feature = "dev-context-only-utils")]
1531 hash_overrides: parent.hash_overrides.clone(),
1532 accounts_lt_hash: Mutex::new(parent.accounts_lt_hash.lock().unwrap().clone()),
1533 accounts_lt_hash_async_progress: Arc::new(AccountsLtHashAsyncProgress::new()),
1534 block_id: RwLock::new(None),
1535 expected_bank_hash: RwLock::new(None),
1536 bank_hash_stats: AtomicBankHashStats::default(),
1537 epoch_rewards_calculation_cache: parent.epoch_rewards_calculation_cache.clone(),
1538 block_component_processor: RwLock::new(BlockComponentProcessor::default()),
1539 is_alpenglow: AtomicBool::new(parent.is_alpenglow()),
1540 };
1541
1542 let (_, ancestors_time_us) = measure_us!({
1543 let mut ancestors = Vec::with_capacity(parent.ancestors.len() + 1);
1544 ancestors.push(new.slot());
1545 ancestors.extend(new.parents_iter().map(|parent| parent.slot()));
1546 new.ancestors = Ancestors::from(ancestors);
1547 });
1548
1549 let prepare_timings = new.prepare_for_block_execution(
1550 parent.epoch(),
1551 parent.slot(),
1552 parent.capitalization(),
1553 parent.block_height(),
1554 reward_calc_tracer,
1555 );
1556
1557 time.stop();
1558 report_new_bank_metrics(
1559 slot,
1560 parent.slot(),
1561 new.block_height,
1562 NewBankTimings {
1563 bank_rc_creation_time_us,
1564 total_elapsed_time_us: time.as_us(),
1565 status_cache_time_us,
1566 fee_components_time_us,
1567 blockhash_queue_time_us,
1568 stakes_cache_time_us,
1569 epoch_stakes_time_us,
1570 builtin_program_ids_time_us,
1571 executor_cache_time_us: 0,
1572 transaction_debug_keys_time_us,
1573 transaction_log_collector_config_time_us,
1574 feature_set_time_us,
1575 ancestors_time_us,
1576 update_epoch_time_us: prepare_timings.update_epoch_time_us,
1577 distribute_rewards_time_us: prepare_timings.distribute_rewards_time_us,
1578 cache_preparation_time_us: prepare_timings.cache_preparation_time_us,
1579 update_sysvars_time_us: prepare_timings.update_sysvars_time_us,
1580 fill_sysvar_cache_time_us: prepare_timings.fill_sysvar_cache_time_us,
1581 },
1582 );
1583
1584 report_loaded_programs_stats(
1585 &parent
1586 .transaction_processor
1587 .global_program_cache
1588 .read()
1589 .unwrap(),
1590 parent.slot(),
1591 );
1592
1593 new.transaction_processor
1594 .global_program_cache
1595 .write()
1596 .unwrap()
1597 .stats
1598 .reset();
1599
1600 new
1601 }
1602
1603 pub fn set_fork_graph_in_program_cache(&self, fork_graph: Weak<RwLock<BankForks>>) {
1604 self.transaction_processor
1605 .global_program_cache
1606 .write()
1607 .unwrap()
1608 .set_fork_graph(fork_graph);
1609 }
1610
1611 fn prepare_program_cache_for_upcoming_feature_set(&self) {
1612 let (_epoch, slot_index) = self.epoch_schedule.get_epoch_and_slot_index(self.slot);
1613 let slots_in_epoch = self.epoch_schedule.get_slots_in_epoch(self.epoch);
1614 let (upcoming_feature_set, _newly_activated) = self.compute_active_feature_set(true);
1615
1616 let slots_in_recompilation_phase =
1618 (solana_program_runtime::loaded_programs::MAX_LOADED_ENTRY_COUNT as u64)
1619 .min(slots_in_epoch)
1620 .checked_div(2)
1621 .unwrap();
1622
1623 let mut epoch_boundary_preparation = self
1624 .transaction_processor
1625 .epoch_boundary_preparation
1626 .write()
1627 .unwrap();
1628
1629 if let Some(upcoming_environment) = epoch_boundary_preparation.upcoming_environment.as_ref()
1630 {
1631 let upcoming_environment = upcoming_environment.clone();
1632 if let Some((key, program_to_recompile)) =
1633 epoch_boundary_preparation.programs_to_recompile.pop()
1634 {
1635 drop(epoch_boundary_preparation);
1636 self.transaction_processor
1637 .prepare_one_program_for_upcoming_feature_set(
1638 self,
1639 &upcoming_environment,
1640 &key,
1641 &program_to_recompile.stats,
1642 );
1643 }
1644 } else if slot_index.saturating_add(slots_in_recompilation_phase) >= slots_in_epoch {
1645 let new_environment = self.create_program_runtime_environment(&upcoming_feature_set);
1648 let mut upcoming_environment = self
1649 .transaction_processor
1650 .program_runtime_environment
1651 .clone();
1652 let changed_program_runtime_environment = *upcoming_environment != *new_environment;
1654 if changed_program_runtime_environment {
1655 upcoming_environment = new_environment;
1656 let program_cache_guard = self
1657 .transaction_processor
1658 .global_program_cache
1659 .read()
1660 .unwrap();
1661 epoch_boundary_preparation.programs_to_recompile = program_cache_guard
1662 .get_flattened_entries()
1663 .into_iter()
1664 .map(|(id, _last_modification_slot, entry)| (id, entry))
1665 .collect();
1666 epoch_boundary_preparation
1667 .programs_to_recompile
1668 .sort_by_cached_key(|(_id, program)| program.retention_score());
1669 } else {
1670 epoch_boundary_preparation.programs_to_recompile.clear();
1671 }
1672 epoch_boundary_preparation.upcoming_epoch = self.epoch.saturating_add(1);
1673 epoch_boundary_preparation.upcoming_environment = Some(upcoming_environment);
1674 }
1675 }
1676
1677 pub fn prune_program_cache(&self, bank_forks: &BankForks) {
1678 let upcoming_environment = self
1679 .transaction_processor
1680 .epoch_boundary_preparation
1681 .write()
1682 .unwrap()
1683 .reroot(self.epoch());
1684 self.transaction_processor
1685 .global_program_cache
1686 .write()
1687 .unwrap()
1688 .prune(
1689 self.slot(),
1690 upcoming_environment.map(|_| {
1691 ProgramRuntimeEnvironment::clone(
1692 &self.transaction_processor.program_runtime_environment,
1693 )
1694 }),
1695 bank_forks,
1696 );
1697 }
1698
1699 pub fn prune_program_cache_by_deployment_slot(&self, deployment_slot: Slot) {
1700 self.transaction_processor
1701 .global_program_cache
1702 .write()
1703 .unwrap()
1704 .prune_by_deployment_slot(deployment_slot);
1705 }
1706
1707 pub fn new_warmup_cooldown_rate_epoch(&self) -> Option<Epoch> {
1709 self.feature_set
1710 .new_warmup_cooldown_rate_epoch(&self.epoch_schedule)
1711 }
1712
1713 fn use_fixed_point_stake_math(&self) -> bool {
1714 self.feature_set
1715 .snapshot()
1716 .upgrade_bpf_stake_program_to_v5_1
1717 }
1718
1719 fn get_cached_vote_accounts<'a>(
1723 &'a self,
1724 rewarded_epoch: Epoch,
1725 distribution_epoch_vote_accounts: &'a VoteAccounts,
1726 ) -> CachedVoteAccounts<'a> {
1727 let snapshot_epoch_vote_accounts = self
1731 .epoch_stakes(rewarded_epoch)
1732 .map(|epoch_stakes| epoch_stakes.stakes().vote_accounts());
1733
1734 let rewarded_epoch_vote_accounts = self
1736 .epoch_stakes(self.epoch())
1737 .map(|epoch_stakes| epoch_stakes.stakes().vote_accounts());
1738
1739 CachedVoteAccounts {
1740 snapshot_epoch_vote_accounts,
1741 rewarded_epoch_vote_accounts,
1742 distribution_epoch_vote_accounts,
1743 }
1744 }
1745
1746 fn compute_new_epoch_caches_and_rewards(
1749 &self,
1750 thread_pool: &ThreadPool,
1751 rewarded_epoch: Epoch,
1752 reward_calc_tracer: Option<impl RewardCalcTracer>,
1753 rewards_metrics: &mut RewardsMetrics,
1754 ) -> NewEpochBundle {
1755 let stakes = self.stakes_cache.stakes();
1759 let stake_delegations = stakes.stake_delegations_vec();
1760 let (
1761 (
1762 stake_history,
1763 unfiltered_distribution_vote_accounts,
1764 delegated_stakes,
1765 reward_epoch_delegated_stakes,
1766 ),
1767 calculate_activated_stake_time_us,
1768 ) = measure_us!(stakes.calculate_activated_stake(
1769 self.epoch(),
1770 thread_pool,
1771 self.new_warmup_cooldown_rate_epoch(),
1772 &stake_delegations,
1773 self.use_fixed_point_stake_math(),
1774 ));
1775 debug_assert_eq!(reward_epoch_delegated_stakes.epoch, rewarded_epoch);
1776
1777 let filtered_distribution_vote_accounts = unfiltered_distribution_vote_accounts
1780 .clone_and_filter_for_vat(
1781 MAX_ALPENGLOW_VOTE_ACCOUNTS,
1782 self.minimum_vote_account_balance_for_vat(),
1783 );
1784 if AlpenglowEpochType::is_alpenglow_or_migration_epoch(self, rewarded_epoch) {
1785 reward_epoch_delegated_stakes.set(self, &filtered_distribution_vote_accounts);
1786 }
1787 let cached_vote_accounts =
1788 self.get_cached_vote_accounts(rewarded_epoch, &filtered_distribution_vote_accounts);
1789 let (rewards_calculation, update_rewards_with_thread_pool_time_us) =
1790 measure_us!(self.calculate_rewards(
1791 &stake_history,
1792 stake_delegations,
1793 cached_vote_accounts,
1794 rewarded_epoch,
1795 reward_epoch_delegated_stakes,
1796 reward_calc_tracer,
1797 thread_pool,
1798 rewards_metrics,
1799 ));
1800 NewEpochBundle {
1801 stake_history,
1802 unfiltered_distribution_vote_accounts,
1803 delegated_stakes,
1804 filtered_distribution_vote_accounts,
1805 rewards_calculation,
1806 calculate_activated_stake_time_us,
1807 update_rewards_with_thread_pool_time_us,
1808 }
1809 }
1810
1811 fn process_new_epoch(
1813 &mut self,
1814 parent_epoch: Epoch,
1815 parent_slot: Slot,
1816 parent_capitalization: u64,
1817 parent_height: u64,
1818 reward_calc_tracer: Option<impl RewardCalcTracer>,
1819 ) {
1820 let epoch = self.epoch();
1821 let slot = self.slot();
1822 let thread_pool = rewards_calculation_thread_pool();
1823
1824 let (_, apply_feature_activations_time_us) = measure_us!(
1825 thread_pool.install(|| { self.compute_and_apply_new_feature_activations() })
1826 );
1827
1828 let mut rewards_metrics = RewardsMetrics::default();
1829 let NewEpochBundle {
1830 stake_history,
1831 unfiltered_distribution_vote_accounts,
1832 delegated_stakes,
1833 filtered_distribution_vote_accounts,
1834 rewards_calculation,
1835 calculate_activated_stake_time_us,
1836 update_rewards_with_thread_pool_time_us,
1837 } = self.compute_new_epoch_caches_and_rewards(
1838 thread_pool,
1839 parent_epoch,
1840 reward_calc_tracer,
1841 &mut rewards_metrics,
1842 );
1843
1844 self.stakes_cache.activate_epoch(
1845 epoch,
1846 stake_history,
1847 unfiltered_distribution_vote_accounts,
1848 delegated_stakes,
1849 );
1850
1851 let leader_schedule_epoch = self.epoch_schedule.get_leader_schedule_epoch(slot);
1853 let (_, update_epoch_stakes_time_us) = measure_us!(self.update_epoch_stakes(
1854 leader_schedule_epoch,
1855 Some(filtered_distribution_vote_accounts),
1856 ));
1857
1858 let (epoch_rewards, begin_partitioned_rewards_time_us) =
1861 measure_us!(self.begin_partitioned_rewards(
1862 parent_epoch,
1863 parent_slot,
1864 parent_height,
1865 &rewards_calculation,
1866 &mut rewards_metrics,
1867 thread_pool,
1868 ));
1869
1870 if self.feature_set.snapshot().alpenglow {
1873 let epoch_start_capitalization = parent_capitalization;
1874 EpochInflationAccountState::new_epoch_update_account(
1875 self,
1876 epoch_start_capitalization,
1877 epoch_rewards,
1878 );
1879 }
1880
1881 report_new_epoch_metrics(
1882 epoch,
1883 slot,
1884 parent_slot,
1885 NewEpochTimings {
1886 apply_feature_activations_time_us,
1887 calculate_activated_stake_time_us,
1888 update_epoch_stakes_time_us,
1889 update_rewards_with_thread_pool_time_us,
1890 begin_partitioned_rewards_time_us,
1891 },
1892 rewards_metrics,
1893 );
1894
1895 let program_runtime_environment =
1896 self.create_program_runtime_environment(&self.feature_set);
1897 self.transaction_processor
1898 .set_program_runtime_environment(program_runtime_environment);
1899 }
1900
1901 pub fn proper_ancestors_set(&self) -> HashSet<Slot> {
1902 HashSet::from_iter(self.proper_ancestors())
1903 }
1904
1905 pub(crate) fn proper_ancestors(&self) -> impl Iterator<Item = Slot> + '_ {
1907 self.ancestors
1908 .keys()
1909 .into_iter()
1910 .filter(move |slot| *slot != self.slot)
1911 }
1912
1913 pub fn set_callback(&self, callback: Option<Box<dyn DropCallback + Send + Sync>>) {
1914 *self.drop_callback.write().unwrap() = OptionalDropCallback(callback);
1915 }
1916
1917 pub fn vote_only_bank(&self) -> bool {
1918 self.vote_only_bank
1919 }
1920
1921 pub fn warp_from_parent(parent: Arc<Bank>, leader: SlotLeader, slot: Slot) -> Self {
1927 parent.freeze();
1928 let parent_timestamp = parent.clock().unix_timestamp;
1929 let mut new = Bank::new_from_parent(parent, leader, slot);
1930 new.update_epoch_stakes(new.epoch_schedule().get_epoch(slot), None);
1931 new.tick_height.store(new.max_tick_height(), Relaxed);
1932
1933 let mut clock = new.clock();
1934 clock.epoch_start_timestamp = parent_timestamp;
1935 clock.unix_timestamp = parent_timestamp;
1936 new.update_sysvar_account(&sysvar::clock::id(), |account| {
1937 create_account(
1938 &clock,
1939 new.inherit_specially_retained_account_fields(account),
1940 )
1941 });
1942 new.transaction_processor
1943 .fill_missing_sysvar_cache_entries(&new);
1944 new.freeze();
1945 new
1946 }
1947
1948 fn load_rent_from_account_for_snapshot_load(
1949 accounts: &Accounts,
1950 ancestors: &Ancestors,
1951 ) -> Rent {
1952 let rent_sysvar = accounts
1955 .load_with_fixed_root_do_not_populate_read_cache(ancestors, &sysvar::rent::id())
1956 .expect("snapshot must contain rent sysvar account")
1957 .0;
1958 from_account::<sysvar::rent::Rent>(&rent_sysvar)
1959 .expect("snapshot must contain well-formed rent sysvar account")
1960 }
1961
1962 fn prepare_for_block_execution(
1967 &mut self,
1968 parent_epoch: Epoch,
1969 parent_slot: Slot,
1970 parent_capitalization: u64,
1971 parent_block_height: u64,
1972 reward_calc_tracer: Option<impl RewardCalcTracer>,
1973 ) -> PrepareBlockExecutionStats {
1974 let slot = self.slot;
1975
1976 let (_, update_epoch_time_us) = measure_us!({
1978 if parent_epoch < self.epoch() {
1979 self.process_new_epoch(
1980 parent_epoch,
1981 parent_slot,
1982 parent_capitalization,
1983 parent_block_height,
1984 reward_calc_tracer,
1985 );
1986 } else {
1987 let leader_schedule_epoch = self.epoch_schedule().get_leader_schedule_epoch(slot);
1989 self.update_epoch_stakes(leader_schedule_epoch, None);
1990 }
1991 });
1992
1993 let (_, distribute_rewards_time_us) =
1994 measure_us!(self.distribute_partitioned_epoch_rewards());
1995
1996 let (_, cache_preparation_time_us) =
1997 measure_us!(self.prepare_program_cache_for_upcoming_feature_set());
1998
1999 let (_, update_sysvars_time_us) = measure_us!({
2001 self.update_slot_hashes();
2002 self.update_stake_history(Some(parent_epoch));
2003
2004 if self.is_alpenglow() {
2005 self.update_clock_slot_for_alpenglow();
2008 } else {
2009 self.update_clock(Some(parent_epoch));
2013 }
2014 self.update_last_restart_slot()
2015 });
2016
2017 let (_, fill_sysvar_cache_time_us) = measure_us!(
2018 self.transaction_processor
2019 .fill_missing_sysvar_cache_entries(self)
2020 );
2021
2022 PrepareBlockExecutionStats {
2023 update_epoch_time_us,
2024 distribute_rewards_time_us,
2025 cache_preparation_time_us,
2026 update_sysvars_time_us,
2027 fill_sysvar_cache_time_us,
2028 }
2029 }
2030
2031 pub(crate) fn new_from_snapshot(
2033 bank_rc: BankRc,
2034 genesis_config: &GenesisConfig,
2035 runtime_config: Arc<RuntimeConfig>,
2036 fields: BankFieldsToDeserialize,
2037 leader_for_tests: Option<SlotLeader>,
2038 debug_keys: Option<Arc<HashSet<Pubkey>>>,
2039 accounts_data_size_initial: u64,
2040 epoch_stakes: HashMap<Epoch, VersionedEpochStakes>,
2041 ) -> Self {
2042 let now = Instant::now();
2043 let slot = fields.slot;
2044 let epoch = fields.epoch_schedule.get_epoch(slot);
2045 let ancestors = Ancestors::from(vec![slot]);
2046 let rewards_calculation_thread_pool = rewards_calculation_thread_pool();
2049 let (stakes, stakes_time) = measure_time!(
2060 Stakes::load_from_deserialized_delegations(fields.stakes, |pubkey| {
2061 let (account, _slot) = bank_rc
2062 .accounts
2063 .load_with_fixed_root_do_not_populate_read_cache(&ancestors, pubkey)?;
2064 Some(account)
2065 })
2066 .expect(
2067 "Stakes cache is inconsistent with accounts-db. This can indicate a corrupted \
2068 snapshot or bugs in cached accounts or accounts-db.",
2069 )
2070 );
2071 info!("Loading Stakes took: {stakes_time}");
2072 assert!(
2073 fields.versioned_epoch_stakes.is_empty(),
2074 "should be already converted and passed in epoch_stakes parameter"
2075 );
2076 assert!(
2077 !epoch_stakes.is_empty(),
2078 "should be populated (from fields.versioned_epoch_stakes)"
2079 );
2080
2081 let compute_leader = || {
2083 if slot == 0 {
2084 stakes
2087 .highest_staked_node()
2088 .expect("genesis snapshot should contain at least one staked vote account")
2089 } else {
2090 Self::slot_leader_from_epoch_stakes(
2091 fields.slot,
2092 &fields.epoch_schedule,
2093 &epoch_stakes,
2094 )
2095 }
2096 };
2097 #[cfg(not(feature = "dev-context-only-utils"))]
2098 let leader = {
2099 _ = leader_for_tests;
2100 compute_leader()
2101 };
2102 #[cfg(feature = "dev-context-only-utils")]
2103 let leader = leader_for_tests.unwrap_or_else(compute_leader);
2104 assert_eq!(
2105 fields.leader_id, leader.id,
2106 "snapshot leader_id does not match computed slot leader"
2107 );
2108
2109 let stakes_accounts_load_duration = now.elapsed();
2110 let rent = Self::load_rent_from_account_for_snapshot_load(&bank_rc.accounts, &ancestors);
2111 let partitioned_rewards_stake_account_stores_per_block = bank_rc
2112 .accounts
2113 .accounts_db
2114 .partitioned_epoch_rewards_config
2115 .stake_account_stores_per_block;
2116 let mut bank = Self {
2117 rc: bank_rc,
2118 status_cache: Arc::<RwLock<BankStatusCache>>::default(),
2119 store_transaction_signatures_in_status_cache: !runtime_config
2120 .skip_transaction_signatures_in_status_cache,
2121 blockhash_queue: RwLock::new(fields.blockhash_queue),
2122 max_processing_age: MAX_PROCESSING_AGE,
2123 partitioned_rewards_stake_account_stores_per_block,
2124 ancestors,
2125 hash: RwLock::new(fields.hash),
2126 parent_hash: fields.parent_hash,
2127 parent_slot: fields.parent_slot,
2128 hard_forks: Arc::new(RwLock::new(fields.hard_forks)),
2129 transaction_count: AtomicU64::new(fields.transaction_count),
2130 non_vote_transaction_count_since_restart: AtomicU64::default(),
2131 transaction_error_count: AtomicU64::default(),
2132 transaction_entries_count: AtomicU64::default(),
2133 transactions_per_entry_max: AtomicU64::default(),
2134 entry_bytes_consumed: EntryBytesBudget::new(DEFAULT_MAX_ENTRY_BYTES_PER_SLOT),
2135 tick_height: AtomicU64::new(fields.tick_height),
2136 signature_count: AtomicU64::new(fields.signature_count),
2137 capitalization: AtomicU64::new(fields.capitalization),
2138 max_tick_height: fields.max_tick_height,
2139 hashes_per_tick: RwLock::new(fields.hashes_per_tick),
2140 ticks_per_slot: fields.ticks_per_slot,
2141 ns_per_slot: fields.ns_per_slot,
2142 genesis_creation_time: fields.genesis_creation_time,
2143 slots_per_year: fields.slots_per_year,
2144 slot_params: SlotParamsArchive::default(),
2145 slot,
2146 bank_id: 0,
2147 epoch,
2148 block_height: fields.block_height,
2149 leader,
2150 fee_rate_governor: fields.fee_rate_governor,
2151 rent_collector: RentCollector::new(
2152 epoch,
2153 fields.epoch_schedule.clone(),
2154 fields.slots_per_year,
2155 rent,
2156 ),
2157 epoch_schedule: fields.epoch_schedule,
2158 inflation: Arc::new(RwLock::new(fields.inflation)),
2159 stakes_cache: StakesCache::new(stakes),
2160 epoch_stakes,
2161 is_delta: AtomicBool::new(fields.is_delta),
2162 rewards: RwLock::new(vec![]),
2163 cluster_type: Some(genesis_config.cluster_type),
2164 transaction_debug_keys: debug_keys,
2165 transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
2166 ),
2167 transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
2168 feature_set: Arc::<FeatureSet>::default(),
2169 reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
2170 drop_callback: RwLock::new(OptionalDropCallback(None)),
2171 freeze_started: AtomicBool::new(fields.hash != Hash::default()),
2172 vote_only_bank: false,
2173 cost_tracker: RwLock::new(CostTracker::default()),
2174 accounts_data_size_initial,
2175 accounts_data_size_delta_on_chain: AtomicI64::new(0),
2176 accounts_data_size_delta_off_chain: AtomicI64::new(0),
2177 epoch_reward_status: EpochRewardStatus::default(),
2178 transaction_processor: TransactionBatchProcessor::default(),
2179 collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
2181 compute_budget: runtime_config.compute_budget,
2182 transaction_account_lock_limit: runtime_config.transaction_account_lock_limit,
2183 fee_structure: FeeStructure::default(),
2184 #[cfg(feature = "dev-context-only-utils")]
2185 hash_overrides: Arc::new(Mutex::new(HashOverrides::default())),
2186 accounts_lt_hash: Mutex::new(fields.accounts_lt_hash),
2187 accounts_lt_hash_async_progress: Arc::new(AccountsLtHashAsyncProgress::new()),
2188 block_id: RwLock::new(fields.block_id),
2189 bank_hash_stats: AtomicBankHashStats::new(&fields.bank_hash_stats),
2190 epoch_rewards_calculation_cache: Arc::new(Mutex::new(HashMap::default())),
2191 expected_bank_hash: RwLock::new(None),
2192 block_component_processor: RwLock::new(BlockComponentProcessor::default()),
2193 is_alpenglow: AtomicBool::new(false),
2194 };
2195
2196 if bank.get_alpenglow_genesis_certificate().is_some() {
2197 bank.set_is_alpenglow();
2198 }
2199
2200 assert_eq!(
2205 bank.genesis_creation_time, genesis_config.creation_time,
2206 "Bank snapshot genesis creation time does not match genesis.bin creation time. The \
2207 snapshot and genesis.bin might pertain to different clusters"
2208 );
2209 assert_eq!(bank.ticks_per_slot, genesis_config.ticks_per_slot);
2210 assert_eq!(bank.max_tick_height, (bank.slot + 1) * bank.ticks_per_slot);
2211 assert_eq!(bank.epoch_schedule, genesis_config.epoch_schedule);
2212
2213 bank.refresh_slot_params_from_snapshot(genesis_config);
2214 bank.initialize_after_snapshot_restore(|| rewards_calculation_thread_pool);
2215
2216 datapoint_info!(
2217 "bank-new-from-fields",
2218 (
2219 "accounts_data_len-from-snapshot",
2220 fields.accounts_data_len as i64,
2221 i64
2222 ),
2223 (
2224 "accounts_data_len-from-generate_index",
2225 accounts_data_size_initial as i64,
2226 i64
2227 ),
2228 (
2229 "stakes_accounts_load_duration_us",
2230 stakes_accounts_load_duration.as_micros(),
2231 i64
2232 ),
2233 );
2234 bank
2235 }
2236
2237 fn slot_leader_from_epoch_stakes(
2239 slot: Slot,
2240 epoch_schedule: &EpochSchedule,
2241 epoch_stakes: &HashMap<Epoch, VersionedEpochStakes>,
2242 ) -> SlotLeader {
2243 let (epoch, slot_index) = epoch_schedule.get_epoch_and_slot_index(slot);
2244 let epoch_vote_accounts = epoch_stakes
2245 .get(&epoch)
2246 .expect("epoch stakes should contain current epoch")
2247 .stakes()
2248 .vote_accounts();
2249 let leader_schedule =
2250 leader_schedule_from_vote_accounts(epoch, epoch_schedule, epoch_vote_accounts.as_ref())
2251 .expect("leader schedule should be computable from epoch stakes");
2252 leader_schedule.get_slot_leader_at_index(slot_index as usize)
2253 }
2254
2255 pub(crate) fn get_fields_to_serialize(&self) -> BankFieldsToSerialize {
2257 BankFieldsToSerialize {
2258 blockhash_queue: self.blockhash_queue.read().unwrap().clone(),
2259 hash: *self.hash.read().unwrap(),
2260 parent_hash: self.parent_hash,
2261 parent_slot: self.parent_slot,
2262 hard_forks: self.hard_forks.read().unwrap().clone(),
2263 transaction_count: self.transaction_count.load(Relaxed),
2264 tick_height: self.tick_height.load(Relaxed),
2265 signature_count: self.signature_count.load(Relaxed),
2266 capitalization: self.capitalization.load(Relaxed),
2267 max_tick_height: self.max_tick_height,
2268 hashes_per_tick: *self.hashes_per_tick.read().unwrap(),
2269 ticks_per_slot: self.ticks_per_slot,
2270 ns_per_slot: self.ns_per_slot,
2271 genesis_creation_time: self.genesis_creation_time,
2272 slots_per_year: self.slots_per_year,
2273 slot: self.slot,
2274 block_height: self.block_height,
2275 leader_id: self.leader.id,
2276 fee_rate_governor: self.fee_rate_governor.clone(),
2277 epoch_schedule: self.epoch_schedule.clone(),
2278 inflation: *self.inflation.read().unwrap(),
2279 stakes: self.stakes_cache.stakes().clone(),
2280 is_delta: self.is_delta.load(Relaxed),
2281 accounts_data_len: self.load_accounts_data_size(),
2282 versioned_epoch_stakes: self.epoch_stakes.clone(),
2283 accounts_lt_hash: self.accounts_lt_hash.lock().unwrap().clone(),
2284 block_id: self.block_id().expect("block id must be set"),
2285 }
2286 }
2287
2288 pub fn leader(&self) -> &SlotLeader {
2289 &self.leader
2290 }
2291
2292 pub fn leader_id(&self) -> &Pubkey {
2293 &self.leader.id
2294 }
2295
2296 pub fn genesis_creation_time(&self) -> UnixTimestamp {
2297 self.genesis_creation_time
2298 }
2299
2300 pub fn slot(&self) -> Slot {
2301 self.slot
2302 }
2303
2304 pub fn bank_id(&self) -> BankId {
2305 self.bank_id
2306 }
2307
2308 pub fn epoch(&self) -> Epoch {
2309 self.epoch
2310 }
2311
2312 pub fn first_normal_epoch(&self) -> Epoch {
2313 self.epoch_schedule().first_normal_epoch
2314 }
2315
2316 pub fn freeze_lock(&self) -> RwLockReadGuard<'_, Hash> {
2317 self.hash.read().unwrap()
2318 }
2319
2320 pub fn wait_for_inflight_commits(&self) {
2327 drop(self.hash.write().unwrap());
2328 }
2329
2330 pub fn hash(&self) -> Hash {
2331 *self.hash.read().unwrap()
2332 }
2333
2334 pub fn is_frozen(&self) -> bool {
2335 *self.hash.read().unwrap() != Hash::default()
2336 }
2337
2338 pub fn freeze_started(&self) -> bool {
2339 self.freeze_started.load(Relaxed)
2340 }
2341
2342 pub fn status_cache_ancestors(&self) -> Vec<u64> {
2343 let (min, mut ancestors) = {
2344 let status_cache = self.status_cache.read().unwrap();
2345 let roots = status_cache.roots();
2346 let mut ancestors = Vec::with_capacity(roots.len() + self.ancestors.len());
2347 let mut min = Slot::MAX;
2348 for root in roots {
2349 ancestors.push(*root);
2350 min = min.min(*root);
2351 }
2352 (if roots.is_empty() { 0 } else { min }, ancestors)
2353 };
2354
2355 ancestors.extend(self.ancestors.iter().filter(|ancestor| *ancestor >= min));
2356 ancestors.sort_unstable();
2357 ancestors.dedup();
2358 ancestors
2359 }
2360
2361 pub fn unix_timestamp_from_genesis(&self) -> i64 {
2363 self.genesis_creation_time.saturating_add(
2364 (self.slot as u128)
2365 .saturating_mul(self.ns_per_slot)
2366 .saturating_div(1_000_000_000) as i64,
2367 )
2368 }
2369
2370 pub fn epoch_stakes_from_slot(&self, slot: Slot) -> Option<&VersionedEpochStakes> {
2372 let epoch = self.epoch_schedule().get_epoch(slot);
2373 self.epoch_stakes(epoch)
2374 }
2375
2376 pub fn get_rank_map(&self, slot: Slot) -> Option<&Arc<BLSPubkeyToRankMap>> {
2378 self.epoch_stakes_from_slot(slot)
2379 .map(|stake| stake.bls_pubkey_to_rank_map())
2380 }
2381
2382 fn update_sysvar_account<F>(&self, pubkey: &Pubkey, updater: F)
2383 where
2384 F: Fn(&Option<AccountSharedData>) -> AccountSharedData,
2385 {
2386 let old_account = self.get_account_with_fixed_root(pubkey);
2387 let mut new_account = updater(&old_account);
2388
2389 self.adjust_sysvar_balance_for_rent(&mut new_account);
2395 self.store_account_and_update_capitalization(pubkey, &new_account);
2396 }
2397
2398 fn inherit_specially_retained_account_fields(
2399 &self,
2400 old_account: &Option<AccountSharedData>,
2401 ) -> InheritableAccountFields {
2402 const RENT_UNADJUSTED_INITIAL_BALANCE: u64 = 1;
2403
2404 (
2405 old_account
2406 .as_ref()
2407 .map(|a| a.lamports())
2408 .unwrap_or(RENT_UNADJUSTED_INITIAL_BALANCE),
2409 old_account
2410 .as_ref()
2411 .map(|a| a.rent_epoch())
2412 .unwrap_or(INITIAL_RENT_EPOCH),
2413 )
2414 }
2415
2416 pub fn clock(&self) -> sysvar::clock::Clock {
2417 from_account(&self.get_account(&sysvar::clock::id()).unwrap_or_default())
2418 .unwrap_or_default()
2419 }
2420
2421 fn update_clock(&self, parent_epoch: Option<Epoch>) {
2422 let mut unix_timestamp = self.clock().unix_timestamp;
2423 let epoch_start_timestamp = {
2425 let epoch = if let Some(epoch) = parent_epoch {
2426 epoch
2427 } else {
2428 self.epoch()
2429 };
2430 let first_slot_in_epoch = self.epoch_schedule().get_first_slot_in_epoch(epoch);
2431 Some((first_slot_in_epoch, self.clock().epoch_start_timestamp))
2432 };
2433 let max_allowable_drift = MaxAllowableDrift {
2434 fast: MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST,
2435 slow: MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
2436 };
2437
2438 let ancestor_timestamp = self.clock().unix_timestamp;
2439 if let Some(timestamp_estimate) =
2440 self.get_timestamp_estimate(max_allowable_drift, epoch_start_timestamp)
2441 {
2442 unix_timestamp = timestamp_estimate;
2443 if timestamp_estimate < ancestor_timestamp {
2444 unix_timestamp = ancestor_timestamp;
2445 }
2446 }
2447 datapoint_info!(
2448 "bank-timestamp-correction",
2449 ("slot", self.slot(), i64),
2450 ("from_genesis", self.unix_timestamp_from_genesis(), i64),
2451 ("corrected", unix_timestamp, i64),
2452 ("ancestor_timestamp", ancestor_timestamp, i64),
2453 );
2454 let mut epoch_start_timestamp =
2455 if parent_epoch.is_some() && parent_epoch.unwrap() != self.epoch() {
2457 unix_timestamp
2458 } else {
2459 self.clock().epoch_start_timestamp
2460 };
2461 if self.slot == 0 {
2462 unix_timestamp = self.unix_timestamp_from_genesis();
2463 epoch_start_timestamp = self.unix_timestamp_from_genesis();
2464 }
2465 let clock = sysvar::clock::Clock {
2466 slot: self.slot,
2467 epoch_start_timestamp,
2468 epoch: self.epoch_schedule().get_epoch(self.slot),
2469 leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
2470 unix_timestamp,
2471 };
2472 self.update_sysvar_account(&sysvar::clock::id(), |account| {
2473 create_account(
2474 &clock,
2475 self.inherit_specially_retained_account_fields(account),
2476 )
2477 });
2478 }
2479
2480 fn update_clock_slot_for_alpenglow(&self) {
2489 let clock = self.clock();
2490 let epoch_start_timestamp = match (self.slot, self.parent()) {
2491 (0, _) => self.unix_timestamp_from_genesis(),
2492 (_, Some(parent)) if parent.epoch() != self.epoch() => clock.unix_timestamp,
2493 _ => clock.epoch_start_timestamp,
2494 };
2495 let clock = sysvar::clock::Clock {
2496 slot: self.slot,
2497 epoch: self.epoch_schedule().get_epoch(self.slot),
2498 leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
2499 epoch_start_timestamp,
2500 unix_timestamp: clock.unix_timestamp,
2501 };
2502 self.update_sysvar_account(&sysvar::clock::id(), |account| {
2503 create_account(
2504 &clock,
2505 self.inherit_specially_retained_account_fields(account),
2506 )
2507 });
2508 }
2509
2510 pub fn update_last_restart_slot(&self) {
2511 let current_last_restart_slot = self
2513 .get_account(&sysvar::last_restart_slot::id())
2514 .and_then(|account| {
2515 let lrs: Option<LastRestartSlot> = from_account(&account);
2516 lrs
2517 })
2518 .map(|account| account.last_restart_slot);
2519
2520 let last_restart_slot = {
2521 let slot = self.slot;
2522 let hard_forks_r = self.hard_forks.read().unwrap();
2523
2524 hard_forks_r
2527 .iter()
2528 .rev()
2529 .find(|(hard_fork, _)| *hard_fork <= slot)
2530 .map(|(slot, _)| *slot)
2531 .unwrap_or(0)
2532 };
2533
2534 if current_last_restart_slot != Some(last_restart_slot) {
2536 self.update_sysvar_account(&sysvar::last_restart_slot::id(), |account| {
2537 create_account(
2538 &LastRestartSlot { last_restart_slot },
2539 self.inherit_specially_retained_account_fields(account),
2540 )
2541 });
2542 }
2543 }
2544
2545 pub fn set_sysvar_for_tests<T>(&self, sysvar: &T)
2546 where
2547 T: Serialize + SysvarId,
2548 {
2549 self.update_sysvar_account(&T::id(), |account| {
2550 create_account_with_bincode(
2551 sysvar,
2552 self.inherit_specially_retained_account_fields(account),
2553 )
2554 });
2555 self.transaction_processor
2558 .reset_and_fill_sysvar_cache_entries(self);
2559 }
2560
2561 fn update_slot_history(&self) {
2562 self.update_sysvar_account(&sysvar::slot_history::id(), |account| {
2563 let mut slot_history = account
2564 .as_ref()
2565 .map(|account| wincode::deserialize::<SlotHistory>(account.data()).unwrap())
2566 .unwrap_or_default();
2567 slot_history.add(self.slot());
2568 create_account(
2569 &slot_history,
2570 self.inherit_specially_retained_account_fields(account),
2571 )
2572 });
2573 }
2574
2575 fn update_slot_hashes(&self) {
2576 self.update_sysvar_account(&sysvar::slot_hashes::id(), |account| {
2577 let mut slot_hashes = account
2578 .as_ref()
2579 .map(|account| wincode::deserialize::<SlotHashes>(account.data()).unwrap())
2580 .unwrap_or_default();
2581 slot_hashes.add(self.parent_slot, self.parent_hash);
2582 create_account(
2583 &slot_hashes,
2584 self.inherit_specially_retained_account_fields(account),
2585 )
2586 });
2587 }
2588
2589 pub fn get_slot_history(&self) -> Option<SlotHistory> {
2590 wincode::deserialize::<SlotHistory>(self.get_account(&sysvar::slot_history::id())?.data())
2591 .ok()
2592 }
2593
2594 fn update_epoch_stakes(
2595 &mut self,
2596 leader_schedule_epoch: Epoch,
2597 prefiltered_distribution_vote_accounts: Option<VoteAccounts>,
2598 ) {
2599 if !self.epoch_stakes.contains_key(&leader_schedule_epoch) {
2603 self.epoch_stakes.retain(|&epoch, _| {
2604 epoch >= leader_schedule_epoch.saturating_sub(MAX_LEADER_SCHEDULE_STAKES - 1)
2607 });
2608 let stakes = match prefiltered_distribution_vote_accounts {
2614 Some(prefiltered) => Stakes::new(prefiltered, self.epoch()),
2615 None => self.get_top_epoch_stakes(),
2616 };
2617 let stakes = SerdeStakesToStakeFormat::from(stakes);
2618 let new_epoch_stakes = VersionedEpochStakes::new(stakes, leader_schedule_epoch);
2619 info!(
2620 "new epoch stakes, epoch: {}, total_stake: {}",
2621 leader_schedule_epoch,
2622 new_epoch_stakes.total_stake(),
2623 );
2624
2625 self.maybe_burn_vat_from_staked_accounts(&new_epoch_stakes);
2626
2627 if log::log_enabled!(log::Level::Trace) {
2630 let vote_stakes: HashMap<_, _> = self
2631 .stakes_cache
2632 .stakes()
2633 .vote_accounts()
2634 .delegated_stakes()
2635 .map(|(pubkey, stake)| (*pubkey, stake))
2636 .collect();
2637 trace!("new epoch stakes, stakes: {vote_stakes:#?}");
2638 }
2639 self.epoch_stakes
2640 .insert(leader_schedule_epoch, new_epoch_stakes);
2641 }
2642 }
2643
2644 fn maybe_burn_vat_from_staked_accounts(&mut self, epoch_stakes: &VersionedEpochStakes) {
2649 let feature_snapshot = self.feature_set.snapshot();
2650 if !feature_snapshot.alpenglow {
2651 return;
2652 }
2653
2654 let vat_to_burn_per_epoch = self.vat_to_burn_per_epoch();
2655 let vote_accounts = epoch_stakes.stakes().vote_accounts();
2656 debug_assert!(vote_accounts.len() <= 2000);
2657 let mut accounts_to_store: Vec<(Pubkey, AccountSharedData)> =
2659 Vec::with_capacity(vote_accounts.len() + 1);
2660 let mut total_vat = 0u64;
2661
2662 for (vote_pubkey, _stake) in vote_accounts.delegated_stakes() {
2665 let mut account = self.get_account(vote_pubkey).unwrap();
2666 total_vat += vat_to_burn_per_epoch;
2667 account.set_lamports(
2668 account
2669 .lamports()
2670 .checked_sub(vat_to_burn_per_epoch)
2671 .expect(
2672 "Vote accounts should have already been filtered to contain enough \
2673 balance for the VAT",
2674 ),
2675 );
2676 accounts_to_store.push((*vote_pubkey, account));
2677 }
2678
2679 let mut incinerator_account = self.get_account(&incinerator::id()).unwrap_or_default();
2681 incinerator_account.set_lamports(
2682 incinerator_account
2683 .lamports()
2684 .checked_add(total_vat)
2685 .unwrap(),
2686 );
2687 accounts_to_store.push((incinerator::id(), incinerator_account));
2688
2689 self.store_accounts((self.slot, accounts_to_store.as_slice()), None);
2690 info!(
2691 "Transferred total VAT of {total_vat} lamports to incinerator from staked vote \
2692 accounts"
2693 );
2694 }
2695
2696 #[cfg(feature = "dev-context-only-utils")]
2697 pub fn set_epoch_stakes_for_test(&mut self, epoch: Epoch, stakes: VersionedEpochStakes) {
2698 self.epoch_stakes.insert(epoch, stakes);
2699 }
2700
2701 fn update_rent(&self) {
2702 self.update_sysvar_account(&sysvar::rent::id(), |account| {
2703 create_account(
2704 &self.rent_collector.rent,
2705 self.inherit_specially_retained_account_fields(account),
2706 )
2707 });
2708 }
2709
2710 fn update_epoch_schedule(&self) {
2711 self.update_sysvar_account(&sysvar::epoch_schedule::id(), |account| {
2712 create_account(
2713 self.epoch_schedule(),
2714 self.inherit_specially_retained_account_fields(account),
2715 )
2716 });
2717 }
2718
2719 fn update_stake_history(&self, epoch: Option<Epoch>) {
2720 if epoch == Some(self.epoch()) {
2721 return;
2722 }
2723 self.update_sysvar_account(&stake_history::id(), |account| {
2725 create_account::<StakeHistory>(
2726 self.stakes_cache.stakes().history(),
2727 self.inherit_specially_retained_account_fields(account),
2728 )
2729 });
2730 }
2731
2732 fn refresh_slot_params(&mut self) {
2734 self.refresh_slot_params_with_baseline(self.slot_params.baseline_params());
2735 }
2736
2737 fn refresh_slot_params_from_snapshot(&mut self, genesis_config: &GenesisConfig) {
2738 let (feature_set, _) = self.compute_active_feature_set(false);
2739 self.refresh_slot_params_with_baseline(
2740 self.snapshot_restore_slot_params_baseline(genesis_config, &feature_set),
2741 );
2742 }
2743
2744 fn refresh_slot_params_with_baseline(&mut self, baseline_params: SlotParams) {
2749 self.slot_params =
2750 SlotParamsArchive::new(&self.feature_set, &self.epoch_schedule, baseline_params);
2751 }
2752
2753 fn genesis_config_slot_params(
2755 genesis_config: &GenesisConfig,
2756 partitioned_rewards_stake_account_stores_per_block: u64,
2757 ) -> SlotParams {
2758 SlotParams::genesis_baseline(
2759 genesis_config.ns_per_slot(),
2760 genesis_config.slots_per_year(),
2761 genesis_config.hashes_per_tick(),
2762 partitioned_rewards_stake_account_stores_per_block,
2763 )
2764 }
2765
2766 fn restored_bank_slot_params(&self) -> SlotParams {
2772 SlotParams::genesis_baseline(
2773 self.ns_per_slot,
2774 self.slots_per_year,
2775 self.hashes_per_tick(),
2776 self.partitioned_rewards_stake_account_stores_per_block,
2777 )
2778 }
2779
2780 fn any_slot_time_reduction_effective(
2785 &self,
2786 feature_set: &FeatureSet,
2787 ns_per_slot: u128,
2788 ) -> bool {
2789 SlotParamsArchive::any_slot_time_reduction_effective(
2790 &self.epoch_schedule,
2791 self.slot,
2792 feature_set,
2793 ns_per_slot,
2794 )
2795 }
2796
2797 fn snapshot_restore_slot_params_baseline(
2805 &self,
2806 genesis_config: &GenesisConfig,
2807 feature_set: &FeatureSet,
2808 ) -> SlotParams {
2809 if self.any_slot_time_reduction_effective(feature_set, genesis_config.ns_per_slot()) {
2810 Self::genesis_config_slot_params(
2811 genesis_config,
2812 self.partitioned_rewards_stake_account_stores_per_block,
2813 )
2814 } else {
2815 self.restored_bank_slot_params()
2819 }
2820 }
2821
2822 fn slot_params_at_slot(&self, slot: Slot) -> SlotParams {
2824 self.slot_params.params_at_slot(slot)
2825 }
2826
2827 fn current_slot_params(&self) -> SlotParams {
2829 self.slot_params_at_slot(self.slot)
2830 }
2831
2832 pub(crate) fn vat_to_burn_per_epoch(&self) -> u64 {
2834 self.current_slot_params().vat_to_burn_per_epoch()
2835 }
2836
2837 pub fn get_vat_health_for_next_epoch(
2838 &self,
2839 vote_account_pubkey: &Pubkey,
2840 ) -> std::result::Result<(), VATHealthError> {
2841 let vote_accounts = self.vote_accounts();
2842
2843 let Some((_, vote_account)) = vote_accounts.get(vote_account_pubkey) else {
2844 return Err(VATHealthError::VoteAccountNotFound);
2845 };
2846
2847 if vote_account
2848 .vote_state_view()
2849 .bls_pubkey_compressed()
2850 .is_none()
2851 {
2852 return Err(VATHealthError::NoBLSPubkey);
2853 }
2854
2855 let my_balance = vote_account.lamports();
2856 let minimum_vote_account_balance_for_vat = self.minimum_vote_account_balance_for_vat();
2857 if vote_account.lamports() < minimum_vote_account_balance_for_vat {
2858 return Err(VATHealthError::InsufficientFundsInVoteAccount(
2859 my_balance,
2860 minimum_vote_account_balance_for_vat,
2861 ));
2862 }
2863
2864 Ok(())
2865 }
2866
2867 pub fn ns_per_slot_at_slot(&self, slot: Slot) -> u128 {
2869 self.slot_params_at_slot(slot).ns_per_slot()
2870 }
2871
2872 fn slots_per_year_for_epoch(&self, epoch: Epoch) -> f64 {
2874 let first_slot = self.epoch_schedule().get_first_slot_in_epoch(epoch);
2875 self.slot_params_at_slot(first_slot).slots_per_year()
2876 }
2877
2878 fn slot_range_duration_in_years(&self, start_slot: Slot, end_slot: Slot) -> f64 {
2880 if start_slot >= end_slot {
2881 return 0.0;
2882 }
2883
2884 let mut cursor = start_slot;
2885 let mut params = self.slot_params.baseline_params();
2886 let mut duration = 0.0;
2887
2888 for (effective_slot, effective_params) in self.slot_params.param_transitions() {
2889 if effective_slot <= start_slot {
2890 params = effective_params;
2891 continue;
2892 }
2893 if effective_slot >= end_slot {
2894 break;
2895 }
2896
2897 duration += (effective_slot - cursor) as f64 / params.slots_per_year();
2898 cursor = effective_slot;
2899 params = effective_params;
2900 }
2901
2902 duration + (end_slot - cursor) as f64 / params.slots_per_year()
2903 }
2904
2905 pub fn slot_range_duration_nanos(&self, start_slot: Slot, end_slot: Slot) -> u128 {
2907 self.slot_params
2908 .slot_range_duration_nanos(start_slot, end_slot)
2909 }
2910
2911 pub fn epoch_duration_in_years(&self, epoch: Epoch) -> f64 {
2912 self.epoch_schedule().get_slots_in_epoch(epoch) as f64
2916 / self.slots_per_year_for_epoch(epoch)
2917 }
2918
2919 pub fn max_processing_age(&self) -> usize {
2920 self.max_processing_age
2921 }
2922
2923 fn get_inflation_start_slot(&self) -> Slot {
2929 let mut slots = self
2930 .feature_set
2931 .full_inflation_features_enabled()
2932 .iter()
2933 .filter_map(|id| self.feature_set.activated_slot(id))
2934 .collect::<Vec<_>>();
2935 slots.sort_unstable();
2936 slots.first().cloned().unwrap_or_else(|| {
2937 self.feature_set
2938 .activated_slot(&feature_set::pico_inflation::id())
2939 .unwrap_or(0)
2940 })
2941 }
2942
2943 fn get_inflation_num_slots(&self) -> u64 {
2945 let inflation_start_slot = self.inflation_start_slot_aligned_to_rewards();
2946 self.epoch_schedule().get_first_slot_in_epoch(self.epoch()) - inflation_start_slot
2947 }
2948
2949 fn inflation_start_slot_aligned_to_rewards(&self) -> Slot {
2951 let inflation_activation_slot = self.get_inflation_start_slot();
2952 self.epoch_schedule().get_first_slot_in_epoch(
2953 self.epoch_schedule()
2954 .get_epoch(inflation_activation_slot)
2955 .saturating_sub(1),
2956 )
2957 }
2958
2959 pub fn slot_in_year_for_inflation(&self) -> f64 {
2961 let num_slots = self.get_inflation_num_slots();
2962 let inflation_start_slot = self.inflation_start_slot_aligned_to_rewards();
2963 self.slot_range_duration_in_years(inflation_start_slot, inflation_start_slot + num_slots)
2964 }
2965
2966 pub(crate) fn calculate_epoch_inflation_rewards(
2969 &self,
2970 capitalization: u64,
2971 epoch: Epoch,
2972 ) -> u64 {
2973 let slot_in_year = self.slot_in_year_for_inflation();
2974 let validator_rate = self.inflation.read().unwrap().validator(slot_in_year);
2975 let epoch_duration_in_years = self.epoch_duration_in_years(epoch);
2976 (validator_rate * capitalization as f64 * epoch_duration_in_years) as u64
2977 }
2978
2979 fn update_recent_blockhashes_locked(&self, locked_blockhash_queue: &BlockhashQueue) {
2980 #[expect(deprecated)]
2981 self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
2982 let recent_blockhash_iter = locked_blockhash_queue.get_recent_blockhashes();
2983 recent_blockhashes_account::create_account_with_data_and_fields(
2984 recent_blockhash_iter,
2985 self.inherit_specially_retained_account_fields(account),
2986 )
2987 });
2988 }
2989
2990 pub fn update_recent_blockhashes(&self) {
2991 let blockhash_queue = self.blockhash_queue.read().unwrap();
2992 self.update_recent_blockhashes_locked(&blockhash_queue);
2993 }
2994
2995 fn get_timestamp_estimate(
2996 &self,
2997 max_allowable_drift: MaxAllowableDrift,
2998 epoch_start_timestamp: Option<(Slot, UnixTimestamp)>,
2999 ) -> Option<UnixTimestamp> {
3000 let mut get_timestamp_estimate_time = Measure::start("get_timestamp_estimate");
3001 let slots_per_epoch = self.epoch_schedule().slots_per_epoch;
3002 let vote_accounts = self.vote_accounts();
3003 let recent_timestamps = vote_accounts.iter().filter_map(|(pubkey, (_, account))| {
3004 let vote_state = account.vote_state_view();
3005 let last_timestamp = vote_state.last_timestamp();
3006 let slot_delta = self.slot().checked_sub(last_timestamp.slot)?;
3007 (slot_delta <= slots_per_epoch)
3008 .then_some((*pubkey, (last_timestamp.slot, last_timestamp.timestamp)))
3009 });
3010 let elapsed_slot_duration = |from_slot: Slot, to_slot: Slot| {
3011 if from_slot >= to_slot {
3012 Duration::ZERO
3013 } else {
3014 Duration::from_nanos_u128(
3015 self.slot_range_duration_nanos(from_slot.saturating_add(1), to_slot),
3016 )
3017 }
3018 };
3019 let epoch = self.epoch_schedule().get_epoch(self.slot());
3020 let stakes = self.epoch_vote_accounts(epoch)?;
3021 let stake_weighted_timestamp = calculate_stake_weighted_timestamp(
3022 recent_timestamps,
3023 stakes,
3024 self.slot(),
3025 elapsed_slot_duration,
3026 epoch_start_timestamp,
3027 max_allowable_drift,
3028 );
3029 get_timestamp_estimate_time.stop();
3030 datapoint_info!(
3031 "bank-timestamp",
3032 (
3033 "get_timestamp_estimate_us",
3034 get_timestamp_estimate_time.as_us(),
3035 i64
3036 ),
3037 );
3038 stake_weighted_timestamp
3039 }
3040
3041 pub fn rehash(&self) {
3049 let mut hash = self.hash.write().unwrap();
3050 let new = self.hash_internal_state();
3051 if new != *hash {
3052 warn!("Updating bank hash to {new}");
3053 *hash = new;
3054 }
3055 }
3056
3057 pub fn freeze(&self) {
3058 let mut hash = self.hash.write().unwrap();
3070 if *hash == Hash::default() {
3071 self.distribute_transaction_fee_details();
3073 self.update_slot_history();
3074 self.run_incinerator();
3075
3076 self.freeze_started.store(true, Relaxed);
3078 self.finish_accounts_lt_hash_updates();
3081 *hash = self.hash_internal_state();
3082 self.rc.accounts.accounts_db.mark_slot_frozen(self.slot());
3083 }
3084 }
3085
3086 pub fn freeze_and_verify_bank_hash(&self) -> std::result::Result<(), (Hash, Hash)> {
3089 self.freeze();
3090 let computed_hash = self.hash();
3091
3092 if let Some(expected_hash) = self.expected_bank_hash()
3093 && expected_hash != computed_hash
3094 {
3095 return Err((expected_hash, computed_hash));
3096 }
3097 Ok(())
3098 }
3099
3100 pub fn set_expected_bank_hash(&self, hash: Hash) {
3103 *self.expected_bank_hash.write().unwrap() = Some(hash);
3104 }
3105
3106 pub fn expected_bank_hash(&self) -> Option<Hash> {
3108 *self.expected_bank_hash.read().unwrap()
3109 }
3110
3111 #[cfg(feature = "dev-context-only-utils")]
3113 pub fn unfreeze_for_ledger_tool(&self) {
3114 self.freeze_started.store(false, Relaxed);
3115 }
3116
3117 pub fn epoch_schedule(&self) -> &EpochSchedule {
3118 &self.epoch_schedule
3119 }
3120
3121 pub fn squash(&self) -> SquashTiming {
3127 self.freeze();
3128
3129 let mut roots = Vec::with_capacity(self.ancestors.len());
3131 roots.push(self.slot());
3132 roots.extend(self.parents_iter().map(|parent| parent.slot()));
3133
3134 let mut total_cache_us = 0;
3135
3136 let mut squash_accounts_time = Measure::start("squash_accounts_time");
3137 for slot in roots.iter().rev() {
3138 let add_root_timing = self.rc.accounts.add_root(*slot);
3140 total_cache_us += add_root_timing.cache_us;
3141 }
3142 squash_accounts_time.stop();
3143
3144 *self.rc.parent.write().unwrap() = None;
3145
3146 let mut squash_cache_time = Measure::start("squash_cache_time");
3147 self.status_cache
3148 .write()
3149 .unwrap()
3150 .add_roots(roots.iter().copied());
3151 squash_cache_time.stop();
3152
3153 SquashTiming {
3154 squash_accounts_ms: squash_accounts_time.as_ms(),
3155 squash_accounts_cache_ms: total_cache_us / 1000,
3156 squash_cache_ms: squash_cache_time.as_ms(),
3157 }
3158 }
3159
3160 pub fn parent(&self) -> Option<Arc<Bank>> {
3162 self.rc.parent.read().unwrap().clone()
3163 }
3164
3165 pub fn parent_slot(&self) -> Slot {
3166 self.parent_slot
3167 }
3168
3169 pub fn parent_hash(&self) -> Hash {
3170 self.parent_hash
3171 }
3172
3173 fn process_genesis_config(
3174 &mut self,
3175 genesis_config: &GenesisConfig,
3176 #[cfg(feature = "dev-context-only-utils")] leader_for_tests: Option<SlotLeader>,
3177 #[cfg(feature = "dev-context-only-utils")] genesis_hash: Option<Hash>,
3178 ) {
3179 self.fee_rate_governor = genesis_config.fee_rate_governor.clone();
3181
3182 for (pubkey, account) in genesis_config.accounts.iter() {
3183 assert!(
3184 self.get_account(pubkey).is_none(),
3185 "{pubkey} repeated in genesis config"
3186 );
3187 let account_shared_data = create_account_shared_data(account);
3188 self.store_account_without_stakes_cache(pubkey, &account_shared_data);
3189 self.capitalization.fetch_add(account.lamports(), Relaxed);
3190 self.accounts_data_size_initial += account.data().len() as u64;
3191 }
3192
3193 for (pubkey, account) in genesis_config.rewards_pools.iter() {
3194 assert!(
3195 self.get_account(pubkey).is_none(),
3196 "{pubkey} repeated in genesis config"
3197 );
3198 let account_shared_data = create_account_shared_data(account);
3199 self.store_account_without_stakes_cache(pubkey, &account_shared_data);
3200 self.accounts_data_size_initial += account.data().len() as u64;
3201 }
3202
3203 self.stakes_cache = StakesCache::new(Stakes::new_from_accounts_for_genesis(
3204 self.new_warmup_cooldown_rate_epoch(),
3205 genesis_config.accounts.iter(),
3206 self.use_fixed_point_stake_math(),
3207 ));
3208
3209 let leader = self.stakes_cache.stakes().highest_staked_node();
3213 #[cfg(feature = "dev-context-only-utils")]
3215 let leader = leader_for_tests
3216 .or(leader)
3217 .or(Some(SlotLeader::new_unique()));
3218 self.leader = leader.expect("genesis processing failed because no staked nodes exist");
3219
3220 #[cfg(not(feature = "dev-context-only-utils"))]
3221 let genesis_hash = genesis_config.hash();
3222 #[cfg(feature = "dev-context-only-utils")]
3223 let genesis_hash = genesis_hash.unwrap_or(genesis_config.hash());
3224
3225 self.blockhash_queue.write().unwrap().genesis_hash(
3226 &genesis_hash,
3227 genesis_config.fee_rate_governor.lamports_per_signature,
3228 );
3229
3230 self.hashes_per_tick = RwLock::new(genesis_config.hashes_per_tick());
3231 self.ticks_per_slot = genesis_config.ticks_per_slot();
3232 self.ns_per_slot = genesis_config.ns_per_slot();
3233 self.genesis_creation_time = genesis_config.creation_time;
3234 self.max_tick_height = (self.slot + 1) * self.ticks_per_slot;
3235 self.slots_per_year = genesis_config.slots_per_year();
3236
3237 self.epoch_schedule = genesis_config.epoch_schedule.clone();
3238 self.refresh_slot_params_with_baseline(Self::genesis_config_slot_params(
3239 genesis_config,
3240 self.partitioned_rewards_stake_account_stores_per_block,
3241 ));
3242
3243 self.inflation = Arc::new(RwLock::new(genesis_config.inflation));
3244
3245 self.rent_collector = RentCollector::new(
3246 self.epoch,
3247 self.epoch_schedule().clone(),
3248 self.slots_per_year,
3249 genesis_config.rent.clone(),
3250 );
3251 }
3252
3253 fn burn_and_purge_account(&self, program_id: &Pubkey, mut account: AccountSharedData) {
3254 let old_data_size = account.data().len();
3255 self.capitalization.fetch_sub(account.lamports(), Relaxed);
3256 account.set_lamports(0);
3259 account.data_as_mut_slice().fill(0);
3260 self.store_account(program_id, &account);
3261 self.calculate_and_update_accounts_data_size_delta_off_chain(old_data_size, 0);
3262 }
3263
3264 pub fn add_precompiled_account(&self, program_id: &Pubkey) {
3266 self.add_precompiled_account_with_owner(program_id, native_loader::id())
3267 }
3268
3269 fn add_precompiled_account_with_owner(&self, program_id: &Pubkey, owner: Pubkey) {
3271 if let Some(account) = self.get_account_with_fixed_root(program_id) {
3272 if account.executable() {
3273 return;
3274 } else {
3275 self.burn_and_purge_account(program_id, account);
3277 }
3278 };
3279
3280 assert!(
3281 !self.freeze_started(),
3282 "Can't change frozen bank by adding not-existing new precompiled program \
3283 ({program_id}). Maybe, inconsistent program activation is detected on snapshot \
3284 restore?"
3285 );
3286
3287 let (lamports, rent_epoch) = self.inherit_specially_retained_account_fields(&None);
3289
3290 let account = AccountSharedData::from(Account {
3291 lamports,
3292 owner,
3293 data: vec![],
3294 executable: true,
3295 rent_epoch,
3296 });
3297 self.store_account_and_update_capitalization(program_id, &account);
3298 }
3299
3300 #[allow(deprecated)]
3301 pub fn set_rent_burn_percentage(&mut self, burn_percent: u8) {
3302 self.rent_collector.rent.burn_percent = burn_percent;
3303 }
3304
3305 pub fn set_hashes_per_tick(&self, hashes_per_tick: Option<u64>) {
3306 *self.hashes_per_tick.write().unwrap() = hashes_per_tick;
3307 }
3308
3309 pub fn last_blockhash(&self) -> Hash {
3311 self.blockhash_queue.read().unwrap().last_hash()
3312 }
3313
3314 pub fn last_blockhash_and_lamports_per_signature(&self) -> (Hash, u64) {
3315 let blockhash_queue = self.blockhash_queue.read().unwrap();
3316 let last_hash = blockhash_queue.last_hash();
3317 let last_lamports_per_signature = blockhash_queue
3318 .get_lamports_per_signature(&last_hash)
3319 .unwrap(); (last_hash, last_lamports_per_signature)
3321 }
3322
3323 pub fn is_blockhash_valid(&self, hash: &Hash) -> bool {
3324 let blockhash_queue = self.blockhash_queue.read().unwrap();
3325 blockhash_queue.is_hash_valid_for_age(hash, self.max_processing_age())
3326 }
3327
3328 pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
3329 self.rent_collector.rent.minimum_balance(data_len).max(1)
3330 }
3331
3332 pub fn get_lamports_per_signature(&self) -> u64 {
3333 self.fee_rate_governor.lamports_per_signature
3334 }
3335
3336 pub fn fee_features(&self) -> FeeFeatures {
3338 FeeFeatures {}
3339 }
3340
3341 pub fn get_lamports_per_signature_for_blockhash(&self, hash: &Hash) -> Option<u64> {
3342 let blockhash_queue = self.blockhash_queue.read().unwrap();
3343 blockhash_queue.get_lamports_per_signature(hash)
3344 }
3345
3346 pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> Option<u64> {
3347 {
3348 let blockhash_queue = self.blockhash_queue.read().unwrap();
3349 blockhash_queue.get_lamports_per_signature(message.recent_blockhash())
3350 }
3351 .or_else(|| {
3352 self.load_message_nonce_data(message, false)
3353 .map(|(_nonce_address, nonce_data)| nonce_data.get_lamports_per_signature())
3354 })?;
3355
3356 let transaction_configuration =
3357 TransactionConfiguration::try_from_sanitized_message(message, &self.feature_set)
3358 .ok()?;
3359 Some(solana_fee::calculate_fee(
3360 message,
3361 self.fee_structure().lamports_per_signature,
3362 transaction_configuration.priority_fee_lamports,
3363 self.fee_features(),
3364 ))
3365 }
3366
3367 pub fn get_blockhash_last_valid_block_height(&self, blockhash: &Hash) -> Option<Slot> {
3368 let blockhash_queue = self.blockhash_queue.read().unwrap();
3369 blockhash_queue
3372 .get_hash_age(blockhash)
3373 .map(|age| self.block_height + self.max_processing_age() as u64 - age)
3374 }
3375
3376 pub fn get_alpenglow_genesis_certificate(&self) -> Option<GenesisCert> {
3385 let acct = self.get_account(&GENESIS_CERTIFICATE_ACCOUNT)?;
3386 (!acct.data().is_empty()).then(|| {
3387 let cert: WireBlockCertMessage = wincode::deserialize(acct.data())
3391 .expect("Programmer error deserializing genesis certificate");
3392 GenesisCert {
3393 block: cert.block,
3394 signature: CertSignature {
3395 signature: cert.signature.signature,
3396 bitmap: cert.signature.bitmap,
3397 },
3398 }
3399 })
3400 }
3401
3402 pub fn is_alpenglow(&self) -> bool {
3403 self.is_alpenglow.load(Relaxed)
3404 }
3405
3406 fn set_is_alpenglow(&self) {
3407 self.is_alpenglow.store(true, Relaxed);
3408 }
3409
3410 pub fn set_alpenglow_genesis_certificate(&self, cert: &GenesisCert) {
3412 let cert = WireBlockCertMessage {
3413 block: cert.block,
3414 signature: WireCertSignature {
3415 signature: cert.signature.signature,
3416 bitmap: cert.signature.bitmap.clone(),
3417 },
3418 };
3419 let data = wincode::serialize(&cert).unwrap();
3420 let lamports = Rent::default().minimum_balance(data.len());
3421 let mut cert_acct = AccountSharedData::new(lamports, data.len(), &system_program::ID);
3422 cert_acct.set_data_from_slice(&data);
3423
3424 self.store_account_and_update_capitalization(&GENESIS_CERTIFICATE_ACCOUNT, &cert_acct);
3425 self.set_is_alpenglow();
3426 }
3427
3428 pub fn update_clock_from_footer(&self, unix_timestamp_nanos: i64) {
3431 if !self.feature_set.snapshot().alpenglow {
3432 return;
3433 }
3434
3435 let unix_timestamp_s = unix_timestamp_nanos / 1_000_000_000;
3444 let epoch_start_timestamp = match (self.slot, self.parent()) {
3445 (0, _) => self.unix_timestamp_from_genesis(),
3446 (_, Some(parent)) if parent.epoch() != self.epoch() => unix_timestamp_s,
3447 _ => self.clock().epoch_start_timestamp,
3448 };
3449
3450 let clock = sysvar::clock::Clock {
3454 slot: self.slot,
3455 epoch_start_timestamp,
3456 epoch: self.epoch_schedule().get_epoch(self.slot),
3457 leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
3458 unix_timestamp: unix_timestamp_s,
3459 };
3460
3461 self.update_sysvar_account(&sysvar::clock::id(), |account| {
3462 create_account(
3463 &clock,
3464 self.inherit_specially_retained_account_fields(account),
3465 )
3466 });
3467
3468 let data = wincode::serialize(&unix_timestamp_nanos).unwrap();
3470 let lamports = Rent::default().minimum_balance(data.len());
3471 let mut alpenclock_acct = AccountSharedData::new(lamports, data.len(), &system_program::ID);
3472 alpenclock_acct.set_data_from_slice(&data);
3473
3474 self.store_account_and_update_capitalization(&NANOSECOND_CLOCK_ACCOUNT, &alpenclock_acct);
3475
3476 self.transaction_processor
3477 .reset_and_fill_sysvar_cache_entries(self);
3478 }
3479
3480 pub fn get_nanosecond_clock(&self) -> Option<i64> {
3483 let acct = self.get_account(&NANOSECOND_CLOCK_ACCOUNT)?;
3484 (!acct.data().is_empty()).then(|| {
3485 wincode::deserialize(acct.data())
3488 .expect("Couldn't deserialize nanosecond resolution clock")
3489 })
3490 }
3491
3492 pub fn confirmed_last_blockhash(&self) -> Hash {
3493 const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
3494
3495 let mut last_parent = None;
3496 for (index, parent) in self.parents_iter().enumerate() {
3497 if index == NUM_BLOCKHASH_CONFIRMATIONS {
3498 return parent.last_blockhash();
3499 }
3500 last_parent = Some(parent);
3501 }
3502 last_parent.map_or_else(|| self.last_blockhash(), |parent| parent.last_blockhash())
3503 }
3504
3505 #[cfg(feature = "dev-context-only-utils")]
3507 pub fn clear_signatures(&self) {
3508 self.status_cache.write().unwrap().clear();
3509 }
3510
3511 pub fn clear_slot_signatures(&self, slot: Slot) {
3512 self.status_cache.write().unwrap().clear_slot_entries(slot);
3513 }
3514
3515 fn update_transaction_statuses(
3516 &self,
3517 sanitized_txs: &[impl TransactionWithMeta],
3518 processing_results: &[TransactionProcessingResult],
3519 ) {
3520 let mut status_cache = self.status_cache.write().unwrap();
3521 assert_eq!(sanitized_txs.len(), processing_results.len());
3522 for (tx, processing_result) in sanitized_txs.iter().zip(processing_results) {
3523 if let Ok(processed_tx) = &processing_result {
3524 status_cache.insert(
3527 tx.recent_blockhash(),
3528 tx.message_hash(),
3529 self.slot(),
3530 processed_tx.status(),
3531 );
3532 if self.store_transaction_signatures_in_status_cache {
3533 status_cache.insert(
3536 tx.recent_blockhash(),
3537 tx.signature(),
3538 self.slot(),
3539 processed_tx.status(),
3540 );
3541 }
3542 }
3543 }
3544 }
3545
3546 fn register_recent_blockhash(&self, blockhash: &Hash, scheduler: &InstalledSchedulerRwLock) {
3550 BankWithScheduler::wait_for_paused_scheduler(self, scheduler);
3553
3554 let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3558
3559 #[cfg(feature = "dev-context-only-utils")]
3560 let blockhash_override = self
3561 .hash_overrides
3562 .lock()
3563 .unwrap()
3564 .get_blockhash_override(self.slot())
3565 .copied()
3566 .inspect(|blockhash_override| {
3567 if blockhash_override != blockhash {
3568 info!(
3569 "bank: slot: {}: overrode blockhash: {} with {}",
3570 self.slot(),
3571 blockhash,
3572 blockhash_override
3573 );
3574 }
3575 });
3576 #[cfg(feature = "dev-context-only-utils")]
3577 let blockhash = blockhash_override.as_ref().unwrap_or(blockhash);
3578
3579 w_blockhash_queue.register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3580 self.update_recent_blockhashes_locked(&w_blockhash_queue);
3581 }
3582
3583 pub fn register_unique_recent_blockhash_for_test(&self) {
3586 self.register_recent_blockhash(
3587 &Hash::new_unique(),
3588 &BankWithScheduler::no_scheduler_available(),
3589 )
3590 }
3591
3592 #[cfg(feature = "dev-context-only-utils")]
3593 pub fn register_recent_blockhash_for_test(
3594 &self,
3595 blockhash: &Hash,
3596 lamports_per_signature: Option<u64>,
3597 ) {
3598 let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3602 if let Some(lamports_per_signature) = lamports_per_signature {
3603 w_blockhash_queue.register_hash(blockhash, lamports_per_signature);
3604 } else {
3605 w_blockhash_queue
3606 .register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3607 }
3608 }
3609
3610 pub fn register_tick(&self, hash: &Hash, scheduler: &InstalledSchedulerRwLock) {
3617 assert!(
3618 !self.freeze_started(),
3619 "register_tick() working on a bank that is already frozen or is undergoing freezing!"
3620 );
3621
3622 if self.is_block_boundary(self.tick_height.load(Relaxed) + 1) {
3623 self.register_recent_blockhash(hash, scheduler);
3624 }
3625
3626 self.tick_height.fetch_add(1, Relaxed);
3632 }
3633
3634 #[cfg(feature = "dev-context-only-utils")]
3635 pub fn register_tick_for_test(&self, hash: &Hash) {
3636 self.register_tick(hash, &BankWithScheduler::no_scheduler_available())
3637 }
3638
3639 #[cfg(feature = "dev-context-only-utils")]
3640 pub fn register_default_tick_for_test(&self) {
3641 self.register_tick_for_test(&Hash::default())
3642 }
3643
3644 pub fn is_complete(&self) -> bool {
3645 self.tick_height() == self.max_tick_height()
3646 }
3647
3648 pub fn is_block_boundary(&self, tick_height: u64) -> bool {
3649 tick_height == self.max_tick_height
3650 }
3651
3652 pub fn get_transaction_account_lock_limit(&self) -> usize {
3654 if let Some(transaction_account_lock_limit) = self.transaction_account_lock_limit {
3655 transaction_account_lock_limit
3656 } else if self.feature_set.snapshot().increase_tx_account_lock_limit {
3657 MAX_TX_ACCOUNT_LOCKS
3658 } else {
3659 64
3660 }
3661 }
3662
3663 pub fn prepare_entry_batch(
3666 &self,
3667 txs: Vec<VersionedTransaction>,
3668 ) -> Result<TransactionBatch<'_, '_, RuntimeTransaction<SanitizedTransaction>>> {
3669 let sanitized_txs = txs
3670 .into_iter()
3671 .map(|tx| {
3672 RuntimeTransaction::try_create(
3673 tx,
3674 MessageHash::Compute,
3675 None,
3676 self,
3677 self.get_reserved_account_keys(),
3678 )
3679 })
3680 .collect::<Result<Vec<_>>>()?;
3681 Ok(TransactionBatch::new(
3682 self.try_lock_accounts(&sanitized_txs),
3683 self,
3684 OwnedOrBorrowed::Owned(sanitized_txs),
3685 ))
3686 }
3687
3688 pub fn try_lock_accounts(&self, txs: &[impl TransactionWithMeta]) -> Vec<Result<()>> {
3690 self.try_lock_accounts_with_results(txs, txs.iter().map(|_| Ok(())))
3691 }
3692
3693 pub fn try_lock_accounts_with_results(
3696 &self,
3697 txs: &[impl TransactionWithMeta],
3698 tx_results: impl Iterator<Item = Result<()>>,
3699 ) -> Vec<Result<()>> {
3700 let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3701
3702 let mut batch_message_hashes = AHashSet::with_capacity(txs.len());
3704 let tx_results = tx_results
3705 .enumerate()
3706 .map(|(i, tx_result)| match tx_result {
3707 Ok(()) => {
3708 if batch_message_hashes.insert(txs[i].message_hash()) {
3710 Ok(())
3711 } else {
3712 Err(TransactionError::AlreadyProcessed)
3713 }
3714 }
3715 Err(e) => Err(e),
3716 });
3717
3718 self.rc
3719 .accounts
3720 .lock_accounts(txs.iter(), tx_results, tx_account_lock_limit)
3721 }
3722
3723 pub fn prepare_sanitized_batch<'a, 'b, Tx: TransactionWithMeta>(
3725 &'a self,
3726 txs: &'b [Tx],
3727 ) -> TransactionBatch<'a, 'b, Tx> {
3728 self.prepare_sanitized_batch_with_results(txs, txs.iter().map(|_| Ok(())))
3729 }
3730
3731 pub fn prepare_sanitized_batch_with_results<'a, 'b, Tx: TransactionWithMeta>(
3734 &'a self,
3735 transactions: &'b [Tx],
3736 transaction_results: impl Iterator<Item = Result<()>>,
3737 ) -> TransactionBatch<'a, 'b, Tx> {
3738 TransactionBatch::new(
3740 self.try_lock_accounts_with_results(transactions, transaction_results),
3741 self,
3742 OwnedOrBorrowed::Borrowed(transactions),
3743 )
3744 }
3745
3746 pub fn prepare_unlocked_batch_from_single_tx<'a, Tx: SVMMessage>(
3748 &'a self,
3749 transaction: &'a Tx,
3750 ) -> TransactionBatch<'a, 'a, Tx> {
3751 let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3752 let lock_result = validate_account_locks(transaction.account_keys(), tx_account_lock_limit);
3753 let mut batch = TransactionBatch::new(
3754 vec![lock_result],
3755 self,
3756 OwnedOrBorrowed::Borrowed(slice::from_ref(transaction)),
3757 );
3758 batch.set_needs_unlock(false);
3759 batch
3760 }
3761
3762 pub fn prepare_locked_batch_from_single_tx<'a, Tx: TransactionWithMeta>(
3764 &'a self,
3765 transaction: &'a Tx,
3766 ) -> TransactionBatch<'a, 'a, Tx> {
3767 self.prepare_sanitized_batch(slice::from_ref(transaction))
3768 }
3769
3770 pub fn resanitize_transaction_minimally(
3771 &self,
3772 transaction: &impl TransactionWithMeta,
3773 sanitized_epoch: Epoch,
3774 alt_invalidation_slot: Slot,
3775 ) -> Result<()> {
3776 if self.vote_only_bank() && !vote_parser::is_valid_vote_only_transaction(transaction) {
3777 return Err(TransactionError::SanitizeFailure);
3778 }
3779
3780 if self.epoch() != sanitized_epoch {
3783 self.check_reserved_keys(transaction)?;
3786
3787 for instr in transaction.instructions_iter() {
3788 if instr.accounts.len() > solana_transaction_context::MAX_ACCOUNTS_PER_INSTRUCTION {
3789 return Err(solana_transaction_error::TransactionError::SanitizeFailure);
3790 }
3791 }
3792 }
3793
3794 if self.slot() > alt_invalidation_slot {
3795 let (_addresses, _deactivation_slot) =
3803 self.load_addresses_from_ref(transaction.message_address_table_lookups())?;
3804 }
3805
3806 Ok(())
3807 }
3808
3809 pub fn simulate_transaction(
3811 &self,
3812 transaction: &impl TransactionWithMeta,
3813 enable_cpi_recording: bool,
3814 ) -> TransactionSimulationResult {
3815 assert!(self.is_frozen(), "simulation bank must be frozen");
3816
3817 self.simulate_transaction_unchecked(transaction, enable_cpi_recording)
3818 }
3819
3820 pub fn simulate_transaction_unchecked(
3823 &self,
3824 transaction: &impl TransactionWithMeta,
3825 enable_cpi_recording: bool,
3826 ) -> TransactionSimulationResult {
3827 let account_keys = transaction.account_keys();
3828 let number_of_accounts = account_keys.len();
3829 let account_overrides = self.get_account_overrides_for_simulation(&account_keys);
3830 let batch = self.prepare_unlocked_batch_from_single_tx(transaction);
3831 let mut timings = ExecuteTimings::default();
3832
3833 let LoadAndExecuteTransactionsOutput {
3834 mut processing_results,
3835 balance_collector,
3836 ..
3837 } = self.load_and_execute_transactions(
3838 &batch,
3839 self.max_processing_age()
3843 .saturating_sub(MAX_TRANSACTION_FORWARDING_DELAY),
3844 &mut timings,
3845 &mut TransactionErrorMetrics::default(),
3846 TransactionProcessingConfig {
3847 account_overrides: Some(&account_overrides),
3848 log_messages_bytes_limit: None,
3849 limit_to_load_programs: true,
3850 recording_config: ExecutionRecordingConfig {
3851 enable_cpi_recording,
3852 enable_log_recording: true,
3853 enable_return_data_recording: true,
3854 enable_transaction_balance_recording: true,
3855 },
3856 drop_on_failure: false,
3857 all_or_nothing: false,
3858 strict_nonce_size_check: true,
3859 drop_noop_transactions: true,
3860 },
3861 );
3862
3863 debug!("simulate_transaction: {timings:?}");
3864
3865 let processing_result = processing_results
3866 .pop()
3867 .unwrap_or(Err(TransactionError::InvalidProgramForExecution));
3868 let (
3869 post_simulation_accounts,
3870 result,
3871 fee,
3872 logs,
3873 return_data,
3874 inner_instructions,
3875 units_consumed,
3876 loaded_accounts_data_size,
3877 ) = match processing_result {
3878 Ok(processed_tx) => {
3879 let executed_units = processed_tx.executed_units();
3880 let loaded_accounts_data_size = processed_tx.loaded_accounts_data_size();
3881
3882 match processed_tx {
3883 ProcessedTransaction::Executed(executed_tx) => {
3884 let details = executed_tx.execution_details;
3885 let post_simulation_accounts = executed_tx
3886 .loaded_transaction
3887 .accounts
3888 .into_iter()
3889 .take(number_of_accounts)
3890 .collect::<Vec<_>>();
3891 (
3892 post_simulation_accounts,
3893 details.status,
3894 Some(executed_tx.loaded_transaction.fee_details.total_fee()),
3895 details.log_messages,
3896 details.return_data,
3897 details.inner_instructions,
3898 executed_units,
3899 loaded_accounts_data_size,
3900 )
3901 }
3902 ProcessedTransaction::FeesOnly(fees_only_tx) => (
3903 vec![],
3904 Err(fees_only_tx.load_error),
3905 Some(fees_only_tx.fee_details.total_fee()),
3906 None,
3907 None,
3908 None,
3909 executed_units,
3910 loaded_accounts_data_size,
3911 ),
3912 ProcessedTransaction::NoOp(no_op_tx) => (
3913 vec![],
3914 Err(no_op_tx.validation_error),
3915 None,
3916 None,
3917 None,
3918 None,
3919 executed_units,
3920 loaded_accounts_data_size,
3921 ),
3922 }
3923 }
3924 Err(error) => (vec![], Err(error), None, None, None, None, 0, 0),
3925 };
3926 let logs = logs.unwrap_or_default();
3927
3928 let (pre_balances, post_balances, pre_token_balances, post_token_balances) =
3929 match balance_collector {
3930 Some(balance_collector) => {
3931 let (mut native_pre, mut native_post, mut token_pre, mut token_post) =
3932 balance_collector.into_vecs();
3933
3934 (
3935 native_pre.pop(),
3936 native_post.pop(),
3937 token_pre.pop(),
3938 token_post.pop(),
3939 )
3940 }
3941 None => (None, None, None, None),
3942 };
3943
3944 TransactionSimulationResult {
3945 result,
3946 logs,
3947 post_simulation_accounts,
3948 units_consumed,
3949 loaded_accounts_data_size,
3950 return_data,
3951 inner_instructions,
3952 fee,
3953 pre_balances,
3954 post_balances,
3955 pre_token_balances,
3956 post_token_balances,
3957 }
3958 }
3959
3960 fn get_account_overrides_for_simulation(&self, account_keys: &AccountKeys) -> AccountOverrides {
3961 let mut account_overrides = AccountOverrides::default();
3962 let slot_history_id = sysvar::slot_history::id();
3963 if account_keys.iter().any(|pubkey| *pubkey == slot_history_id) {
3964 let current_account = self.get_account_with_fixed_root(&slot_history_id);
3965 let slot_history = current_account
3966 .as_ref()
3967 .map(|account| wincode::deserialize::<SlotHistory>(account.data()).unwrap())
3968 .unwrap_or_default();
3969 if slot_history.check(self.slot()) == Check::Found {
3970 let ancestors = Ancestors::from(self.proper_ancestors().collect::<Vec<_>>());
3971 if let Some((account, _)) =
3972 self.load_slow_with_fixed_root(&ancestors, &slot_history_id)
3973 {
3974 account_overrides.set_slot_history(Some(account));
3975 }
3976 }
3977 }
3978 account_overrides
3979 }
3980
3981 pub fn unlock_accounts<'a, Tx: SVMMessage + 'a>(
3982 &self,
3983 txs_and_results: impl Iterator<Item = (&'a Tx, &'a Result<()>)> + Clone,
3984 ) {
3985 self.rc.accounts.unlock_accounts(txs_and_results)
3986 }
3987
3988 pub fn remove_unrooted_slots(&self, slots: &[(Slot, BankId)]) {
3989 self.rc.accounts.accounts_db.remove_unrooted_slots(slots)
3990 }
3991
3992 pub fn get_hash_age(&self, hash: &Hash) -> Option<u64> {
3993 self.blockhash_queue.read().unwrap().get_hash_age(hash)
3994 }
3995
3996 pub fn is_hash_valid_for_age(&self, hash: &Hash, max_age: usize) -> bool {
3997 self.blockhash_queue
3998 .read()
3999 .unwrap()
4000 .is_hash_valid_for_age(hash, max_age)
4001 }
4002
4003 pub fn collect_balances(
4004 &self,
4005 batch: &TransactionBatch<impl SVMMessage>,
4006 ) -> TransactionBalances {
4007 let mut balances: TransactionBalances = vec![];
4008 for transaction in batch.sanitized_transactions() {
4009 let mut transaction_balances: Vec<u64> = vec![];
4010 for account_key in transaction.account_keys().iter() {
4011 transaction_balances.push(self.get_balance(account_key));
4012 }
4013 balances.push(transaction_balances);
4014 }
4015 balances
4016 }
4017
4018 pub fn load_and_execute_transactions(
4019 &self,
4020 batch: &TransactionBatch<impl TransactionWithMeta>,
4021 max_age: usize,
4022 timings: &mut ExecuteTimings,
4023 error_counters: &mut TransactionErrorMetrics,
4024 processing_config: TransactionProcessingConfig,
4025 ) -> LoadAndExecuteTransactionsOutput {
4026 let sanitized_txs = batch.sanitized_transactions();
4027
4028 let (check_results, check_us) = measure_us!(self.check_transactions(
4029 sanitized_txs,
4030 batch.lock_results(),
4031 max_age,
4032 processing_config.strict_nonce_size_check,
4033 error_counters,
4034 ));
4035 timings.saturating_add_in_place(ExecuteTimingType::CheckUs, check_us);
4036
4037 let (blockhash, blockhash_lamports_per_signature) =
4038 self.last_blockhash_and_lamports_per_signature();
4039 let effective_epoch_of_deployments =
4040 self.epoch_schedule().get_epoch(self.slot.saturating_add(
4041 solana_program_runtime::program_cache_entry::DELAY_VISIBILITY_SLOT_OFFSET,
4042 ));
4043 let processing_environment = TransactionProcessingEnvironment {
4044 blockhash,
4045 blockhash_lamports_per_signature,
4046 alpenglow_migration_succeeded: self.is_alpenglow(),
4047 epoch_total_stake: self.get_current_epoch_total_stake(),
4048 feature_set: self.feature_set.runtime_features(),
4049 program_runtime_environments: ProgramRuntimeEnvironments::new(
4050 self.transaction_processor
4051 .program_runtime_environment
4052 .clone(),
4053 self.transaction_processor
4054 .program_runtime_environment_for_epoch(effective_epoch_of_deployments),
4055 ),
4056 rent: self.rent_collector.rent.clone(),
4057 };
4058
4059 let sanitized_output = self
4060 .transaction_processor
4061 .load_and_execute_sanitized_transactions(
4062 self,
4063 sanitized_txs,
4064 check_results,
4065 &processing_environment,
4066 &processing_config,
4067 );
4068
4069 error_counters.accumulate(&sanitized_output.error_metrics);
4071
4072 timings.accumulate(&sanitized_output.execute_timings);
4074
4075 let ((), collect_logs_us) =
4076 measure_us!(self.collect_logs(sanitized_txs, &sanitized_output.processing_results));
4077 timings.saturating_add_in_place(ExecuteTimingType::CollectLogsUs, collect_logs_us);
4078
4079 let mut processed_counts = ProcessedTransactionCounts::default();
4080 let err_count = &mut error_counters.total;
4081
4082 for (processing_result, tx) in sanitized_output
4083 .processing_results
4084 .iter()
4085 .zip(sanitized_txs)
4086 {
4087 if let Some(debug_keys) = &self.transaction_debug_keys {
4088 for key in tx.account_keys().iter() {
4089 if debug_keys.contains(key) {
4090 let result = processing_result.flattened_result();
4091 info!("slot: {} result: {:?} tx: {:?}", self.slot, result, tx);
4092 break;
4093 }
4094 }
4095 }
4096
4097 if processing_result.was_processed() {
4098 processed_counts.signature_count +=
4102 tx.signature_details().num_transaction_signatures();
4103 processed_counts.processed_transactions_count += 1;
4104
4105 if !tx.is_simple_vote_transaction() {
4106 processed_counts.processed_non_vote_transactions_count += 1;
4107 }
4108 }
4109
4110 match processing_result.flattened_result() {
4111 Ok(()) => {
4112 processed_counts.processed_with_successful_result_count += 1;
4113 }
4114 Err(err) => {
4115 if err_count.0 == 0 {
4116 debug!("tx error: {err:?} {tx:?}");
4117 }
4118 *err_count += 1;
4119 }
4120 }
4121 }
4122
4123 LoadAndExecuteTransactionsOutput {
4124 processing_results: sanitized_output.processing_results,
4125 processed_counts,
4126 balance_collector: sanitized_output.balance_collector,
4127 }
4128 }
4129
4130 fn collect_logs(
4131 &self,
4132 transactions: &[impl TransactionWithMeta],
4133 processing_results: &[TransactionProcessingResult],
4134 ) {
4135 let transaction_log_collector_config =
4136 self.transaction_log_collector_config.read().unwrap();
4137 if transaction_log_collector_config.filter == TransactionLogCollectorFilter::None {
4138 return;
4139 }
4140
4141 let collected_logs: Vec<_> = processing_results
4142 .iter()
4143 .zip(transactions)
4144 .filter_map(|(processing_result, transaction)| {
4145 let processed_tx = processing_result.processed_transaction()?;
4147 let execution_details = processed_tx.execution_details()?;
4149 Self::collect_transaction_logs(
4150 &transaction_log_collector_config,
4151 transaction,
4152 execution_details,
4153 )
4154 })
4155 .collect();
4156
4157 if !collected_logs.is_empty() {
4158 let mut transaction_log_collector = self.transaction_log_collector.write().unwrap();
4159 for (log, filtered_mentioned_addresses) in collected_logs {
4160 let transaction_log_index = transaction_log_collector.logs.len();
4161 transaction_log_collector.logs.push(log);
4162 for key in filtered_mentioned_addresses.into_iter() {
4163 transaction_log_collector
4164 .mentioned_address_map
4165 .entry(key)
4166 .or_default()
4167 .push(transaction_log_index);
4168 }
4169 }
4170 }
4171 }
4172
4173 fn collect_transaction_logs(
4174 transaction_log_collector_config: &TransactionLogCollectorConfig,
4175 transaction: &impl TransactionWithMeta,
4176 execution_details: &TransactionExecutionDetails,
4177 ) -> Option<(TransactionLogInfo, Vec<Pubkey>)> {
4178 let log_messages = execution_details.log_messages.as_ref()?;
4180
4181 let mut filtered_mentioned_addresses = Vec::new();
4182 if !transaction_log_collector_config
4183 .mentioned_addresses
4184 .is_empty()
4185 {
4186 for key in transaction.account_keys().iter() {
4187 if transaction_log_collector_config
4188 .mentioned_addresses
4189 .contains(key)
4190 {
4191 filtered_mentioned_addresses.push(*key);
4192 }
4193 }
4194 }
4195
4196 let is_vote = transaction.is_simple_vote_transaction();
4197 let store = match transaction_log_collector_config.filter {
4198 TransactionLogCollectorFilter::All => {
4199 !is_vote || !filtered_mentioned_addresses.is_empty()
4200 }
4201 TransactionLogCollectorFilter::AllWithVotes => true,
4202 TransactionLogCollectorFilter::None => false,
4203 TransactionLogCollectorFilter::OnlyMentionedAddresses => {
4204 !filtered_mentioned_addresses.is_empty()
4205 }
4206 };
4207
4208 if store {
4209 Some((
4210 TransactionLogInfo {
4211 signature: *transaction.signature(),
4212 result: execution_details.status.clone(),
4213 is_vote,
4214 log_messages: log_messages.clone(),
4215 },
4216 filtered_mentioned_addresses,
4217 ))
4218 } else {
4219 None
4220 }
4221 }
4222
4223 pub fn load_accounts_data_size(&self) -> u64 {
4225 self.accounts_data_size_initial
4226 .saturating_add_signed(self.load_accounts_data_size_delta())
4227 }
4228
4229 pub fn load_accounts_data_size_delta(&self) -> i64 {
4231 let delta_on_chain = self.load_accounts_data_size_delta_on_chain();
4232 let delta_off_chain = self.load_accounts_data_size_delta_off_chain();
4233 delta_on_chain.saturating_add(delta_off_chain)
4234 }
4235
4236 pub fn load_accounts_data_size_delta_on_chain(&self) -> i64 {
4239 self.accounts_data_size_delta_on_chain.load(Acquire)
4240 }
4241
4242 pub fn load_accounts_data_size_delta_off_chain(&self) -> i64 {
4245 self.accounts_data_size_delta_off_chain.load(Acquire)
4246 }
4247
4248 fn update_accounts_data_size_delta_on_chain(&self, amount: i64) {
4251 if amount == 0 {
4252 return;
4253 }
4254
4255 self.accounts_data_size_delta_on_chain
4256 .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_on_chain| {
4257 Some(accounts_data_size_delta_on_chain.saturating_add(amount))
4258 })
4259 .unwrap();
4261 }
4262
4263 fn update_accounts_data_size_delta_off_chain(&self, amount: i64) {
4266 if amount == 0 {
4267 return;
4268 }
4269
4270 self.accounts_data_size_delta_off_chain
4271 .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_off_chain| {
4272 Some(accounts_data_size_delta_off_chain.saturating_add(amount))
4273 })
4274 .unwrap();
4276 }
4277
4278 fn calculate_and_update_accounts_data_size_delta_off_chain(
4280 &self,
4281 old_data_size: usize,
4282 new_data_size: usize,
4283 ) {
4284 let data_size_delta = calculate_data_size_delta(old_data_size, new_data_size);
4285 self.update_accounts_data_size_delta_off_chain(data_size_delta);
4286 }
4287
4288 fn filter_program_errors_and_collect_fee_details(
4289 &self,
4290 processing_results: &[TransactionProcessingResult],
4291 ) {
4292 let mut accumulated_fee_details = FeeDetails::default();
4293
4294 processing_results.iter().for_each(|processing_result| {
4295 if let Ok(processed_tx) = processing_result {
4296 accumulated_fee_details.accumulate(&processed_tx.fee_details());
4297 }
4298 });
4299
4300 self.collector_fee_details
4301 .write()
4302 .unwrap()
4303 .accumulate(&accumulated_fee_details);
4304 }
4305
4306 fn update_bank_hash_stats<'a>(&self, accounts: &impl StorableAccounts<'a>) {
4307 let mut stats = BankHashStats::default();
4308 (0..accounts.len()).for_each(|i| {
4309 accounts.account(i, |account| {
4310 stats.update(&account);
4311 })
4312 });
4313 self.bank_hash_stats.accumulate(&stats);
4314 }
4315
4316 pub fn commit_transactions(
4317 &self,
4318 sanitized_txs: &[impl TransactionWithMeta],
4319 processing_results: Vec<TransactionProcessingResult>,
4320 processed_counts: &ProcessedTransactionCounts,
4321 timings: &mut ExecuteTimings,
4322 ) -> Vec<TransactionCommitResult> {
4323 assert!(
4324 !self.freeze_started(),
4325 "commit_transactions() working on a bank that is already frozen or is undergoing \
4326 freezing!"
4327 );
4328
4329 let ProcessedTransactionCounts {
4330 processed_transactions_count,
4331 processed_non_vote_transactions_count,
4332 processed_with_successful_result_count,
4333 signature_count,
4334 } = *processed_counts;
4335
4336 self.increment_transaction_count(processed_transactions_count);
4337 self.increment_non_vote_transaction_count_since_restart(
4338 processed_non_vote_transactions_count,
4339 );
4340 self.increment_signature_count(signature_count);
4341
4342 let processed_with_failure_result_count =
4343 processed_transactions_count.saturating_sub(processed_with_successful_result_count);
4344 self.transaction_error_count
4345 .fetch_add(processed_with_failure_result_count, Relaxed);
4346
4347 if processed_transactions_count > 0 {
4348 self.is_delta.store(true, Relaxed);
4349 self.transaction_entries_count.fetch_add(1, Relaxed);
4350 self.transactions_per_entry_max
4351 .fetch_max(processed_transactions_count, Relaxed);
4352 }
4353
4354 let ((), store_accounts_us) = measure_us!({
4355 let maybe_transaction_refs = self
4359 .accounts()
4360 .accounts_db
4361 .has_accounts_update_notifier()
4362 .then(|| {
4363 sanitized_txs
4364 .iter()
4365 .map(|tx| tx.as_sanitized_transaction())
4366 .collect::<Vec<_>>()
4367 });
4368
4369 let (accounts_to_store, transactions) = collect_accounts_to_store(
4370 sanitized_txs,
4371 &maybe_transaction_refs,
4372 &processing_results,
4373 );
4374
4375 let to_store = (self.slot(), accounts_to_store.as_slice());
4376 self.update_bank_hash_stats(&to_store);
4377 self.enqueue_on_chain_accounts_lt_hash_updates(&to_store);
4378 self.rc.accounts.store_accounts_seq(
4381 to_store,
4382 self.bank_id(),
4383 transactions.as_deref(),
4384 &self.ancestors,
4385 );
4386 });
4387
4388 let ((), update_stakes_cache_us) =
4391 measure_us!(self.update_stakes_cache(sanitized_txs, &processing_results));
4392
4393 let ((), update_executors_us) = measure_us!({
4394 let mut cache = None;
4395 for processing_result in &processing_results {
4396 if let Some(ProcessedTransaction::Executed(executed_tx)) =
4397 processing_result.processed_transaction()
4398 {
4399 let programs_modified_by_tx = &executed_tx.programs_modified_by_tx;
4400 if executed_tx.was_successful() && !programs_modified_by_tx.is_empty() {
4401 cache
4402 .get_or_insert_with(|| {
4403 self.transaction_processor
4404 .global_program_cache
4405 .write()
4406 .unwrap()
4407 })
4408 .merge(
4409 &self.transaction_processor.program_runtime_environment,
4410 self.slot,
4411 programs_modified_by_tx,
4412 );
4413 }
4414 }
4415 }
4416 });
4417
4418 let accounts_data_len_delta = processing_results
4419 .iter()
4420 .filter_map(|processing_result| processing_result.processed_transaction())
4421 .filter_map(|processed_tx| processed_tx.execution_details())
4422 .filter_map(|details| details.accounts_deltas.as_ref())
4423 .map(|deltas| {
4424 deltas
4425 .accounts_resize_delta
4426 .saturating_sub_unsigned(deltas.accounts_uninitialized_size)
4427 })
4428 .sum();
4429 self.update_accounts_data_size_delta_on_chain(accounts_data_len_delta);
4430
4431 let ((), update_transaction_statuses_us) =
4432 measure_us!(self.update_transaction_statuses(sanitized_txs, &processing_results));
4433
4434 self.filter_program_errors_and_collect_fee_details(&processing_results);
4435
4436 timings.saturating_add_in_place(ExecuteTimingType::StoreUs, store_accounts_us);
4437 timings.saturating_add_in_place(
4438 ExecuteTimingType::UpdateStakesCacheUs,
4439 update_stakes_cache_us,
4440 );
4441 timings.saturating_add_in_place(ExecuteTimingType::UpdateExecutorsUs, update_executors_us);
4442 timings.saturating_add_in_place(
4443 ExecuteTimingType::UpdateTransactionStatuses,
4444 update_transaction_statuses_us,
4445 );
4446
4447 Self::create_commit_results(processing_results)
4448 }
4449
4450 fn create_commit_results(
4451 processing_results: Vec<TransactionProcessingResult>,
4452 ) -> Vec<TransactionCommitResult> {
4453 processing_results
4454 .into_iter()
4455 .map(|processing_result| {
4456 let processing_result = processing_result?;
4457 let executed_units = processing_result.executed_units();
4458 let loaded_accounts_data_size = processing_result.loaded_accounts_data_size();
4459
4460 match processing_result {
4461 ProcessedTransaction::Executed(executed_tx) => {
4462 let successful = executed_tx.was_successful();
4463 let execution_details = executed_tx.execution_details;
4464 let LoadedTransaction {
4465 accounts: loaded_accounts,
4466 fee_details,
4467 rollback_accounts,
4468 ..
4469 } = executed_tx.loaded_transaction;
4470
4471 let fee_payer_post_balance = if successful {
4473 loaded_accounts[0].1.lamports()
4474 } else {
4475 rollback_accounts.fee_payer().1.lamports()
4476 };
4477
4478 Ok(CommittedTransaction {
4479 status: execution_details.status,
4480 log_messages: execution_details.log_messages,
4481 inner_instructions: execution_details.inner_instructions,
4482 return_data: execution_details.return_data,
4483 executed_units,
4484 fee_details,
4485 loaded_account_stats: TransactionLoadedAccountsStats {
4486 loaded_accounts_count: loaded_accounts.len(),
4487 loaded_accounts_data_size,
4488 },
4489 fee_payer_post_balance,
4490 })
4491 }
4492 ProcessedTransaction::FeesOnly(fees_only_tx) => Ok(CommittedTransaction {
4493 status: Err(fees_only_tx.load_error),
4494 log_messages: None,
4495 inner_instructions: None,
4496 return_data: None,
4497 executed_units,
4498 fee_details: fees_only_tx.fee_details,
4499 loaded_account_stats: TransactionLoadedAccountsStats {
4500 loaded_accounts_count: fees_only_tx.rollback_accounts.count(),
4501 loaded_accounts_data_size,
4502 },
4503 fee_payer_post_balance: fees_only_tx
4504 .rollback_accounts
4505 .fee_payer()
4506 .1
4507 .lamports(),
4508 }),
4509 ProcessedTransaction::NoOp(no_op_tx) => Ok(CommittedTransaction {
4510 status: Err(no_op_tx.validation_error),
4511 log_messages: None,
4512 inner_instructions: None,
4513 return_data: None,
4514 executed_units,
4515 fee_details: FeeDetails::default(),
4516 loaded_account_stats: TransactionLoadedAccountsStats {
4517 loaded_accounts_count: 0,
4518 loaded_accounts_data_size,
4519 },
4520 fee_payer_post_balance: no_op_tx.fee_payer_balance.unwrap_or(0),
4521 }),
4522 }
4523 })
4524 .collect()
4525 }
4526
4527 fn run_incinerator(&self) {
4528 if let Some((account, _)) =
4529 self.get_account_modified_since_parent_with_fixed_root(&incinerator::id())
4530 {
4531 self.capitalization.fetch_sub(account.lamports(), Relaxed);
4532 self.store_account(&incinerator::id(), &AccountSharedData::default());
4533 }
4534 }
4535
4536 pub(crate) fn get_accounts_for_bank_hash_details(&self) -> Vec<(Pubkey, AccountSharedData)> {
4539 let mut accounts = self
4540 .rc
4541 .accounts
4542 .accounts_db
4543 .get_pubkey_account_for_slot(self.slot());
4544 accounts.sort_unstable_by_key(|a| a.0);
4546 accounts
4547 }
4548
4549 pub fn cluster_type(&self) -> ClusterType {
4550 self.cluster_type.unwrap()
4553 }
4554
4555 #[must_use]
4557 pub fn load_execute_and_commit_transactions(
4558 &self,
4559 batch: &TransactionBatch<impl TransactionWithMeta>,
4560 recording_config: ExecutionRecordingConfig,
4561 timings: &mut ExecuteTimings,
4562 log_messages_bytes_limit: Option<usize>,
4563 ) -> (Vec<TransactionCommitResult>, Option<BalanceCollector>) {
4564 self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4565 batch,
4566 recording_config,
4567 timings,
4568 log_messages_bytes_limit,
4569 None::<fn(&_) -> _>,
4570 )
4571 .unwrap()
4572 }
4573
4574 pub fn load_execute_and_commit_transactions_with_pre_commit_callback(
4575 &self,
4576 batch: &TransactionBatch<impl TransactionWithMeta>,
4577 recording_config: ExecutionRecordingConfig,
4578 timings: &mut ExecuteTimings,
4579 log_messages_bytes_limit: Option<usize>,
4580 pre_commit_callback: impl FnOnce(&[TransactionProcessingResult]) -> Result<()>,
4581 ) -> Result<(Vec<TransactionCommitResult>, Option<BalanceCollector>)> {
4582 self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4583 batch,
4584 recording_config,
4585 timings,
4586 log_messages_bytes_limit,
4587 Some(pre_commit_callback),
4588 )
4589 }
4590
4591 fn do_load_execute_and_commit_transactions_with_pre_commit_callback(
4592 &self,
4593 batch: &TransactionBatch<impl TransactionWithMeta>,
4594 recording_config: ExecutionRecordingConfig,
4595 timings: &mut ExecuteTimings,
4596 log_messages_bytes_limit: Option<usize>,
4597 pre_commit_callback: Option<impl FnOnce(&[TransactionProcessingResult]) -> Result<()>>,
4598 ) -> Result<(Vec<TransactionCommitResult>, Option<BalanceCollector>)> {
4599 let LoadAndExecuteTransactionsOutput {
4600 processing_results,
4601 processed_counts,
4602 balance_collector,
4603 } = self.load_and_execute_transactions(
4604 batch,
4605 self.max_processing_age(),
4606 timings,
4607 &mut TransactionErrorMetrics::default(),
4608 TransactionProcessingConfig {
4609 account_overrides: None,
4610 log_messages_bytes_limit,
4611 limit_to_load_programs: false,
4612 recording_config,
4613 drop_on_failure: false,
4614 all_or_nothing: false,
4615 strict_nonce_size_check: false,
4616 drop_noop_transactions: false,
4617 },
4618 );
4619
4620 if let Some(pre_commit_callback) = pre_commit_callback {
4621 let () = pre_commit_callback(&processing_results)?;
4622 }
4623
4624 let commit_results = self.commit_transactions(
4625 batch.sanitized_transactions(),
4626 processing_results,
4627 &processed_counts,
4628 timings,
4629 );
4630 Ok((commit_results, balance_collector))
4631 }
4632
4633 pub fn process_transaction(&self, tx: &Transaction) -> Result<()> {
4636 self.try_process_transactions(std::iter::once(tx))?[0].clone()
4637 }
4638
4639 pub fn process_transaction_with_metadata(
4642 &self,
4643 tx: impl Into<VersionedTransaction>,
4644 ) -> Result<CommittedTransaction> {
4645 let txs = vec![tx.into()];
4646 let batch = self.prepare_entry_batch(txs)?;
4647
4648 let (mut commit_results, ..) = self.load_execute_and_commit_transactions(
4649 &batch,
4650 ExecutionRecordingConfig {
4651 enable_cpi_recording: false,
4652 enable_log_recording: true,
4653 enable_return_data_recording: true,
4654 enable_transaction_balance_recording: false,
4655 },
4656 &mut ExecuteTimings::default(),
4657 Some(1000 * 1000),
4658 );
4659
4660 commit_results.remove(0)
4661 }
4662
4663 pub fn try_process_transactions<'a>(
4666 &self,
4667 txs: impl Iterator<Item = &'a Transaction>,
4668 ) -> Result<Vec<Result<()>>> {
4669 let txs = txs
4670 .map(|tx| VersionedTransaction::from(tx.clone()))
4671 .collect();
4672 self.try_process_entry_transactions(txs)
4673 }
4674
4675 pub fn try_process_entry_transactions(
4678 &self,
4679 txs: Vec<VersionedTransaction>,
4680 ) -> Result<Vec<Result<()>>> {
4681 let batch = self.prepare_entry_batch(txs)?;
4682 Ok(self.process_transaction_batch(&batch))
4683 }
4684
4685 #[must_use]
4686 fn process_transaction_batch(
4687 &self,
4688 batch: &TransactionBatch<impl TransactionWithMeta>,
4689 ) -> Vec<Result<()>> {
4690 self.load_execute_and_commit_transactions(
4691 batch,
4692 ExecutionRecordingConfig::new_single_setting(false),
4693 &mut ExecuteTimings::default(),
4694 None,
4695 )
4696 .0
4697 .into_iter()
4698 .map(|commit_result| commit_result.and_then(|committed_tx| committed_tx.status))
4699 .collect()
4700 }
4701
4702 pub fn transfer(&self, n: u64, keypair: &Keypair, to: &Pubkey) -> Result<Signature> {
4705 let blockhash = self.last_blockhash();
4706 let tx = system_transaction::transfer(keypair, to, n, blockhash);
4707 let signature = tx.signatures[0];
4708 self.process_transaction(&tx).map(|_| signature)
4709 }
4710
4711 pub fn read_balance(account: &AccountSharedData) -> u64 {
4712 account.lamports()
4713 }
4714 pub fn get_balance(&self, pubkey: &Pubkey) -> u64 {
4717 self.get_account(pubkey)
4718 .map(|x| Self::read_balance(&x))
4719 .unwrap_or(0)
4720 }
4721
4722 pub fn parents(&self) -> Vec<Arc<Bank>> {
4724 self.parents_iter().collect()
4725 }
4726
4727 pub(crate) fn parents_iter(&self) -> impl Iterator<Item = Arc<Bank>> + '_ {
4728 let mut bank = self.parent();
4729 core::iter::from_fn(move || {
4730 let parent = bank.take()?;
4731 bank = parent.parent();
4732 Some(parent)
4733 })
4734 }
4735
4736 pub fn parents_inclusive(self: Arc<Self>) -> Vec<Arc<Bank>> {
4738 let mut parents = Vec::with_capacity(self.ancestors.len());
4739 parents.push(Arc::clone(&self));
4740 parents.extend(self.parents_iter());
4741 parents
4742 }
4743
4744 pub fn store_account(&self, pubkey: &Pubkey, account: &AccountSharedData) {
4747 self.store_accounts((self.slot(), &[(pubkey, account)][..]), None)
4748 }
4749
4750 pub fn store_accounts<'a>(
4756 &self,
4757 accounts: impl StorableAccounts<'a>,
4758 thread_pool_for_loading_accounts: Option<&ThreadPool>,
4759 ) {
4760 assert!(!self.freeze_started());
4761 let mut m = Measure::start("stakes_cache.check_and_store");
4762 let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
4763 let use_fixed_point_stake_math = self.use_fixed_point_stake_math();
4764
4765 (0..accounts.len()).for_each(|i| {
4766 accounts.account(i, |account| {
4767 self.stakes_cache.check_and_store(
4768 account.pubkey(),
4769 &account,
4770 new_warmup_cooldown_rate_epoch,
4771 use_fixed_point_stake_math,
4772 )
4773 })
4774 });
4775 self.store_accounts_without_stakes_cache(accounts, thread_pool_for_loading_accounts);
4776 m.stop();
4777 self.rc
4778 .accounts
4779 .accounts_db
4780 .stats
4781 .stakes_cache_check_and_store_us
4782 .fetch_add(m.as_us(), Relaxed);
4783 }
4784
4785 fn store_account_without_stakes_cache(&self, pubkey: &Pubkey, account: &AccountSharedData) {
4786 self.store_accounts_without_stakes_cache((self.slot(), &[(pubkey, account)][..]), None)
4787 }
4788
4789 fn store_accounts_without_stakes_cache<'a>(
4795 &self,
4796 accounts: impl StorableAccounts<'a>,
4797 thread_pool_for_loading_accounts: Option<&ThreadPool>,
4798 ) {
4799 assert!(!self.freeze_started());
4800 self.update_bank_hash_stats(&accounts);
4801 self.enqueue_off_chain_accounts_lt_hash_updates(
4802 &accounts,
4803 thread_pool_for_loading_accounts,
4804 );
4805 self.rc
4806 .accounts
4807 .store_accounts_par(accounts, self.bank_id(), None, &self.ancestors);
4808 }
4809
4810 pub fn force_flush_accounts_cache(&self) {
4811 self.rc
4812 .accounts
4813 .accounts_db
4814 .flush_accounts_cache(true, Some(self.slot()))
4815 }
4816
4817 pub(crate) fn store_account_and_update_capitalization(
4820 &self,
4821 pubkey: &Pubkey,
4822 new_account: &AccountSharedData,
4823 ) {
4824 let old_account_data_size = if let Some(old_account) =
4825 self.get_account_with_fixed_root_no_cache(pubkey)
4826 {
4827 match new_account.lamports().cmp(&old_account.lamports()) {
4828 std::cmp::Ordering::Greater => {
4829 let diff = new_account.lamports() - old_account.lamports();
4830 trace!("store_account_and_update_capitalization: increased: {pubkey} {diff}");
4831 self.capitalization.fetch_add(diff, Relaxed);
4832 }
4833 std::cmp::Ordering::Less => {
4834 let diff = old_account.lamports() - new_account.lamports();
4835 trace!("store_account_and_update_capitalization: decreased: {pubkey} {diff}");
4836 self.capitalization.fetch_sub(diff, Relaxed);
4837 }
4838 std::cmp::Ordering::Equal => {}
4839 }
4840 old_account.data().len()
4841 } else {
4842 trace!(
4843 "store_account_and_update_capitalization: created: {pubkey} {}",
4844 new_account.lamports()
4845 );
4846 self.capitalization
4847 .fetch_add(new_account.lamports(), Relaxed);
4848 0
4849 };
4850
4851 self.store_account(pubkey, new_account);
4852
4853 let new_account_data_size = if new_account.lamports() == 0 {
4855 0
4856 } else {
4857 new_account.data().len()
4858 };
4859 self.calculate_and_update_accounts_data_size_delta_off_chain(
4860 old_account_data_size,
4861 new_account_data_size,
4862 );
4863 }
4864
4865 pub fn accounts(&self) -> Arc<Accounts> {
4866 self.rc.accounts.clone()
4867 }
4868
4869 fn apply_cost_tracker_limits_for_active_features(&mut self) {
4871 let params = self.current_slot_params();
4872 let cost_limits =
4873 params.cost_limits(self.feature_set.snapshot().raise_block_limits_to_100m);
4874
4875 let mut cost_tracker = self.write_cost_tracker().unwrap();
4876 cost_tracker.set_limits(cost_limits);
4877 }
4878
4879 fn apply_partitioned_epoch_rewards_config_for_active_features(&mut self) {
4881 self.partitioned_rewards_stake_account_stores_per_block = self
4882 .current_slot_params()
4883 .partitioned_epoch_rewards_stake_account_stores_per_block();
4884 }
4885
4886 fn apply_slot_time_persistent_changes(&mut self) {
4888 let params = self.current_slot_params();
4889 self.ns_per_slot = params.ns_per_slot();
4890 self.slots_per_year = params.slots_per_year();
4891 self.rent_collector.slots_per_year = params.slots_per_year();
4892 if !self.feature_set.is_active(&feature_set::alpenglow::id())
4893 && self.hashes_per_tick().is_some()
4894 {
4895 self.set_hashes_per_tick(params.hashes_per_tick());
4896 }
4897 }
4898
4899 fn assert_bank_matches_slot_params(&self) {
4901 let params = self.current_slot_params();
4902 assert_eq!(
4903 self.ns_per_slot,
4904 params.ns_per_slot(),
4905 "snapshot slot-time ns_per_slot mismatch"
4906 );
4907 assert_eq!(
4908 self.slots_per_year.to_bits(),
4909 params.slots_per_year().to_bits(),
4910 "snapshot slot-time slots_per_year mismatch"
4911 );
4912 assert_eq!(
4913 self.rent_collector.slots_per_year.to_bits(),
4914 params.slots_per_year().to_bits(),
4915 "snapshot slot-time rent_collector.slots_per_year mismatch"
4916 );
4917 let hashes_per_tick = self.hashes_per_tick();
4918 if !self.feature_set.is_active(&feature_set::alpenglow::id()) && hashes_per_tick.is_some() {
4919 assert_eq!(
4920 hashes_per_tick,
4921 params.hashes_per_tick(),
4922 "snapshot slot-time hashes_per_tick mismatch"
4923 );
4924 }
4925 assert_eq!(
4926 self.entry_bytes_budget().slot_limit(),
4927 params.max_entry_bytes_per_slot(),
4928 "snapshot slot-time entry byte budget mismatch"
4929 );
4930 }
4931
4932 fn apply_slot_time_runtime_changes(&mut self) {
4935 self.entry_bytes_consumed =
4936 EntryBytesBudget::new(self.current_slot_params().max_entry_bytes_per_slot());
4937 self.apply_cost_tracker_limits_for_active_features();
4938 self.apply_partitioned_epoch_rewards_config_for_active_features();
4939 }
4940
4941 fn apply_simd_0339_invoke_cost_changes(&mut self) {
4942 let simd_0268_active = self.feature_set.snapshot().raise_cpi_nesting_limit_to_8;
4943 let compute_budget = self
4944 .compute_budget()
4945 .as_ref()
4946 .unwrap_or(&ComputeBudget::new_with_defaults(simd_0268_active))
4947 .to_cost();
4948
4949 self.transaction_processor
4950 .set_execution_cost(compute_budget);
4951 }
4952
4953 fn apply_activated_features(&mut self) {
4955 self.reserved_account_keys = {
4957 let mut reserved_keys = ReservedAccountKeys::clone(&self.reserved_account_keys);
4958 reserved_keys.update_active_set(&self.feature_set);
4959 Arc::new(reserved_keys)
4960 };
4961
4962 self.refresh_slot_params();
4965 self.apply_slot_time_runtime_changes();
4966 self.apply_simd_0339_invoke_cost_changes();
4967
4968 let program_runtime_environment =
4969 self.create_program_runtime_environment(&self.feature_set);
4970 self.transaction_processor
4971 .global_program_cache
4972 .write()
4973 .unwrap()
4974 .latest_root_slot = self.slot;
4975 self.transaction_processor
4976 .epoch_boundary_preparation
4977 .write()
4978 .unwrap()
4979 .upcoming_epoch = self.epoch;
4980 self.transaction_processor.program_runtime_environment = program_runtime_environment;
4981
4982 self.add_active_builtin_programs();
4984 }
4985
4986 fn create_program_runtime_environment(
4987 &self,
4988 feature_set: &FeatureSet,
4989 ) -> ProgramRuntimeEnvironment {
4990 let simd_0268_active = feature_set.snapshot().raise_cpi_nesting_limit_to_8;
4991 let compute_budget = self
4992 .compute_budget()
4993 .as_ref()
4994 .unwrap_or(&ComputeBudget::new_with_defaults(simd_0268_active))
4995 .to_budget();
4996 create_program_runtime_environment(
4997 &feature_set.runtime_features(),
4998 &compute_budget,
4999 false, false, )
5002 .unwrap()
5003 }
5004
5005 pub fn set_tick_height(&self, tick_height: u64) {
5006 self.tick_height.store(tick_height, Relaxed)
5007 }
5008
5009 pub fn set_inflation(&self, inflation: Inflation) {
5010 *self.inflation.write().unwrap() = inflation;
5011 }
5012
5013 pub fn hard_forks(&self) -> HardForks {
5015 self.hard_forks.read().unwrap().clone()
5016 }
5017
5018 pub fn register_hard_fork(&self, new_hard_fork_slot: Slot) {
5019 let bank_slot = self.slot();
5020
5021 let lock = self.freeze_lock();
5022 let bank_frozen = *lock != Hash::default();
5023 if new_hard_fork_slot < bank_slot {
5024 warn!(
5025 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is older than the \
5026 bank at slot {bank_slot} that attempted to register it."
5027 );
5028 } else if (new_hard_fork_slot == bank_slot) && bank_frozen {
5029 warn!(
5030 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is the same slot \
5031 as the bank at slot {bank_slot} that attempted to register it, but that bank is \
5032 already frozen."
5033 );
5034 } else {
5035 self.hard_forks
5036 .write()
5037 .unwrap()
5038 .register(new_hard_fork_slot);
5039 }
5040 }
5041
5042 pub fn register_hard_forks(&self, new_hard_fork_slots: Option<&Vec<Slot>>) {
5043 if let Some(slots) = new_hard_fork_slots {
5044 slots
5045 .iter()
5046 .for_each(|hard_fork_slot| self.register_hard_fork(*hard_fork_slot));
5047 }
5048 }
5049
5050 pub fn get_account_with_fixed_root_no_cache(
5051 &self,
5052 pubkey: &Pubkey,
5053 ) -> Option<AccountSharedData> {
5054 self.rc
5055 .accounts
5056 .load_with_fixed_root_do_not_populate_read_cache(&self.ancestors, pubkey)
5057 .map(|(acc, _slot)| acc)
5058 }
5059
5060 pub fn get_account(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
5064 self.get_account_modified_slot(pubkey)
5065 .map(|(acc, _slot)| acc)
5066 }
5067
5068 pub fn get_account_with_fixed_root(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
5075 self.get_account_modified_slot_with_fixed_root(pubkey)
5076 .map(|(acc, _slot)| acc)
5077 }
5078
5079 pub fn get_account_modified_slot_with_fixed_root(
5081 &self,
5082 pubkey: &Pubkey,
5083 ) -> Option<(AccountSharedData, Slot)> {
5084 self.load_slow_with_fixed_root(&self.ancestors, pubkey)
5085 }
5086
5087 pub fn get_account_modified_slot(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
5088 self.load_slow(&self.ancestors, pubkey)
5089 }
5090
5091 fn load_slow(
5092 &self,
5093 ancestors: &Ancestors,
5094 pubkey: &Pubkey,
5095 ) -> Option<(AccountSharedData, Slot)> {
5096 self.rc.accounts.load_without_fixed_root(ancestors, pubkey)
5100 }
5101
5102 fn load_slow_with_fixed_root(
5103 &self,
5104 ancestors: &Ancestors,
5105 pubkey: &Pubkey,
5106 ) -> Option<(AccountSharedData, Slot)> {
5107 self.rc.accounts.load_with_fixed_root(ancestors, pubkey)
5108 }
5109
5110 pub fn get_program_accounts(
5111 &self,
5112 program_id: &Pubkey,
5113 ) -> ScanResult<Vec<KeyedAccountSharedData>> {
5114 self.rc
5115 .accounts
5116 .load_by_program(&self.ancestors, self.bank_id, program_id)
5117 }
5118
5119 pub fn get_filtered_program_accounts<F: Fn(&AccountSharedData) -> bool>(
5120 &self,
5121 program_id: &Pubkey,
5122 filter: F,
5123 ) -> ScanResult<Vec<KeyedAccountSharedData>> {
5124 self.rc.accounts.load_by_program_with_filter(
5125 &self.ancestors,
5126 self.bank_id,
5127 program_id,
5128 filter,
5129 )
5130 }
5131
5132 pub fn get_filtered_indexed_accounts<F: Fn(&AccountSharedData) -> bool>(
5133 &self,
5134 index_key: &IndexKey,
5135 filter: F,
5136 byte_limit_for_scan: Option<usize>,
5137 ) -> ScanResult<Vec<KeyedAccountSharedData>> {
5138 self.rc.accounts.load_by_index_key_with_filter(
5139 &self.ancestors,
5140 self.bank_id,
5141 index_key,
5142 filter,
5143 byte_limit_for_scan,
5144 )
5145 }
5146
5147 pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
5148 self.rc.accounts.account_indexes_include_key(key)
5149 }
5150
5151 pub fn scan_all_accounts<F>(&self, scan_func: F) -> ScanResult<()>
5153 where
5154 F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>),
5155 {
5156 self.rc
5157 .accounts
5158 .scan_all(&self.ancestors, self.bank_id, scan_func)
5159 }
5160
5161 pub fn get_program_accounts_modified_since_parent(
5162 &self,
5163 program_id: &Pubkey,
5164 ) -> Vec<KeyedAccountSharedData> {
5165 self.rc
5166 .accounts
5167 .load_by_program_slot(self.slot(), Some(program_id))
5168 }
5169
5170 pub fn get_transaction_logs(
5171 &self,
5172 address: Option<&Pubkey>,
5173 ) -> Option<Vec<TransactionLogInfo>> {
5174 self.transaction_log_collector
5175 .read()
5176 .unwrap()
5177 .get_logs_for_address(address)
5178 }
5179
5180 pub fn get_all_accounts_modified_since_parent(&self) -> Vec<KeyedAccountSharedData> {
5182 self.rc.accounts.load_by_program_slot(self.slot(), None)
5183 }
5184
5185 fn get_account_modified_since_parent_with_fixed_root(
5187 &self,
5188 pubkey: &Pubkey,
5189 ) -> Option<(AccountSharedData, Slot)> {
5190 let just_self: Ancestors = Ancestors::from(vec![self.slot()]);
5191 if let Some((account, slot)) = self.load_slow_with_fixed_root(&just_self, pubkey)
5192 && slot == self.slot()
5193 {
5194 return Some((account, slot));
5195 }
5196 None
5197 }
5198
5199 pub fn get_largest_accounts(
5200 &self,
5201 num: usize,
5202 filter_by_address: &HashSet<Pubkey>,
5203 filter: AccountAddressFilter,
5204 ) -> ScanResult<Vec<(Pubkey, u64)>> {
5205 self.rc.accounts.load_largest_accounts(
5206 &self.ancestors,
5207 self.bank_id,
5208 num,
5209 filter_by_address,
5210 filter,
5211 )
5212 }
5213
5214 pub fn transaction_count(&self) -> u64 {
5216 self.transaction_count.load(Relaxed)
5217 }
5218
5219 pub fn non_vote_transaction_count_since_restart(&self) -> u64 {
5224 self.non_vote_transaction_count_since_restart.load(Relaxed)
5225 }
5226
5227 pub fn executed_transaction_count(&self) -> u64 {
5229 self.transaction_count()
5230 .saturating_sub(self.parent().map_or(0, |parent| parent.transaction_count()))
5231 }
5232
5233 pub fn transaction_error_count(&self) -> u64 {
5234 self.transaction_error_count.load(Relaxed)
5235 }
5236
5237 pub fn transaction_entries_count(&self) -> u64 {
5238 self.transaction_entries_count.load(Relaxed)
5239 }
5240
5241 pub fn transactions_per_entry_max(&self) -> u64 {
5242 self.transactions_per_entry_max.load(Relaxed)
5243 }
5244
5245 pub fn max_data_shreds_per_slot(&self) -> u32 {
5246 self.max_data_shreds_per_slot_for_slot(self.slot())
5247 }
5248
5249 pub fn max_code_shreds_per_slot(&self) -> u32 {
5250 self.max_code_shreds_per_slot_for_slot(self.slot())
5251 }
5252
5253 pub fn max_data_shreds_per_slot_for_slot(&self, slot: Slot) -> u32 {
5258 self.slot_params_at_slot(slot).max_data_shreds_per_slot()
5259 }
5260
5261 pub fn max_code_shreds_per_slot_for_slot(&self, slot: Slot) -> u32 {
5266 self.slot_params_at_slot(slot).max_code_shreds_per_slot()
5267 }
5268
5269 pub fn max_entry_bytes_per_slot(&self) -> u64 {
5270 self.entry_bytes_budget().slot_limit()
5271 }
5272
5273 pub fn entry_bytes_budget(&self) -> &EntryBytesBudget {
5274 &self.entry_bytes_consumed
5275 }
5276
5277 fn increment_transaction_count(&self, tx_count: u64) {
5278 self.transaction_count.fetch_add(tx_count, Relaxed);
5279 }
5280
5281 fn increment_non_vote_transaction_count_since_restart(&self, tx_count: u64) {
5282 self.non_vote_transaction_count_since_restart
5283 .fetch_add(tx_count, Relaxed);
5284 }
5285
5286 pub fn signature_count(&self) -> u64 {
5287 self.signature_count.load(Relaxed)
5288 }
5289
5290 fn increment_signature_count(&self, signature_count: u64) {
5291 self.signature_count.fetch_add(signature_count, Relaxed);
5292 }
5293
5294 pub fn get_signature_status_processed_since_parent(
5295 &self,
5296 signature: &Signature,
5297 ) -> Option<Result<()>> {
5298 if let Some((slot, status)) = self.get_signature_status_slot(signature)
5299 && slot <= self.slot()
5300 {
5301 return Some(status);
5302 }
5303 None
5304 }
5305
5306 pub fn get_signature_status_with_blockhash(
5307 &self,
5308 signature: &Signature,
5309 blockhash: &Hash,
5310 ) -> Option<Result<()>> {
5311 let rcache = self.status_cache.read().unwrap();
5312 rcache
5313 .get_status(signature, blockhash, &self.ancestors)
5314 .map(|v| v.1)
5315 }
5316
5317 pub fn get_committed_transaction_status_and_slot(
5318 &self,
5319 message_hash: &Hash,
5320 transaction_blockhash: &Hash,
5321 ) -> Option<(Slot, bool)> {
5322 let rcache = self.status_cache.read().unwrap();
5323 rcache
5324 .get_status(message_hash, transaction_blockhash, &self.ancestors)
5325 .map(|(slot, status)| (slot, status.is_ok()))
5326 }
5327
5328 pub fn get_signature_status_slot(&self, signature: &Signature) -> Option<(Slot, Result<()>)> {
5329 let rcache = self.status_cache.read().unwrap();
5330 rcache.get_status_any_blockhash(signature, &self.ancestors)
5331 }
5332
5333 pub fn get_signature_status(&self, signature: &Signature) -> Option<Result<()>> {
5334 self.get_signature_status_slot(signature).map(|v| v.1)
5335 }
5336
5337 pub fn has_signature(&self, signature: &Signature) -> bool {
5338 self.get_signature_status_slot(signature).is_some()
5339 }
5340
5341 fn hash_internal_state(&self) -> Hash {
5344 let measure_total = Measure::start("");
5345 let slot = self.slot();
5346
5347 let mut hash = hashv(&[
5348 self.parent_hash.as_ref(),
5349 &self.signature_count().to_le_bytes(),
5350 self.last_blockhash().as_ref(),
5351 ]);
5352
5353 let accounts_lt_hash_checksum = {
5354 let accounts_lt_hash = &*self.accounts_lt_hash.lock().unwrap();
5355 let lt_hash_bytes = bytemuck::must_cast_slice(&accounts_lt_hash.0.0);
5356 hash = hashv(&[hash.as_ref(), lt_hash_bytes]);
5357 accounts_lt_hash.0.checksum()
5358 };
5359
5360 let buf = self
5361 .hard_forks
5362 .read()
5363 .unwrap()
5364 .get_hash_data(slot, self.parent_slot());
5365 if let Some(buf) = buf {
5366 let hard_forked_hash = hashv(&[hash.as_ref(), &buf]);
5367 warn!("hard fork at slot {slot} by hashing {buf:?}: {hash} => {hard_forked_hash}");
5368 hash = hard_forked_hash;
5369 }
5370
5371 #[cfg(feature = "dev-context-only-utils")]
5372 let hash_override = self
5373 .hash_overrides
5374 .lock()
5375 .unwrap()
5376 .get_bank_hash_override(slot)
5377 .copied()
5378 .inspect(|&hash_override| {
5379 if hash_override != hash {
5380 info!(
5381 "bank: slot: {}: overrode bank hash: {} with {}",
5382 self.slot(),
5383 hash,
5384 hash_override
5385 );
5386 }
5387 });
5388 #[cfg(feature = "dev-context-only-utils")]
5392 let hash = hash_override.unwrap_or(std::hint::black_box(hash));
5393
5394 let bank_hash_stats = self.bank_hash_stats.load();
5395
5396 let total_us = measure_total.end_as_us();
5397
5398 datapoint_info!(
5399 "bank-hash_internal_state",
5400 ("slot", slot, i64),
5401 ("total_us", total_us, i64),
5402 );
5403 info!(
5404 "bank frozen: {slot} hash: {hash} signature_count: {} last_blockhash: {} \
5405 capitalization: {}, accounts_lt_hash checksum: {accounts_lt_hash_checksum}, stats: \
5406 {bank_hash_stats:?}",
5407 self.signature_count(),
5408 self.last_blockhash(),
5409 self.capitalization(),
5410 );
5411 hash
5412 }
5413
5414 pub fn run_final_hash_calc(&self) {
5417 self.force_flush_accounts_cache();
5418 _ = self.verify_accounts(None);
5420 }
5421
5422 #[must_use]
5435 fn verify_accounts(&self, calculated_accounts_lt_hash: Option<&AccountsLtHash>) -> bool {
5436 let accounts_db = &self.rc.accounts.accounts_db;
5437
5438 fn check_lt_hash(
5439 expected_accounts_lt_hash: &AccountsLtHash,
5440 calculated_accounts_lt_hash: &AccountsLtHash,
5441 ) -> bool {
5442 let is_ok = calculated_accounts_lt_hash == expected_accounts_lt_hash;
5443 if !is_ok {
5444 let expected = expected_accounts_lt_hash.0.checksum();
5445 let calculated = calculated_accounts_lt_hash.0.checksum();
5446 error!(
5447 "Verifying accounts failed: accounts lattice hashes do not match, expected: \
5448 {expected}, calculated: {calculated}",
5449 );
5450 }
5451 is_ok
5452 }
5453
5454 info!("Verifying accounts...");
5455 let start = Instant::now();
5456 let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5457 let is_ok = if let Some(calculated_accounts_lt_hash) = calculated_accounts_lt_hash {
5458 check_lt_hash(&expected_accounts_lt_hash, calculated_accounts_lt_hash)
5459 } else {
5460 let calculated_accounts_lt_hash =
5461 accounts_db.calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors);
5462 check_lt_hash(&expected_accounts_lt_hash, &calculated_accounts_lt_hash)
5463 };
5464 info!("Verifying accounts... Done in {:?}", start.elapsed());
5465 is_ok
5466 }
5467
5468 pub fn get_snapshot_storages(&self, base_slot: Option<Slot>) -> Vec<Arc<AccountStorageEntry>> {
5472 let start_slot = base_slot.map_or(0, |slot| slot.saturating_add(1));
5474 let requested_slots = start_slot..=self.slot();
5476
5477 self.rc.accounts.accounts_db.get_storages(requested_slots).0
5478 }
5479
5480 #[must_use]
5481 fn verify_hash(&self) -> bool {
5482 assert!(self.is_frozen());
5483 let calculated_hash = self.hash_internal_state();
5484 let expected_hash = self.hash();
5485
5486 if calculated_hash == expected_hash {
5487 true
5488 } else {
5489 warn!(
5490 "verify failed: slot: {}, {} (calculated) != {} (expected)",
5491 self.slot(),
5492 calculated_hash,
5493 expected_hash
5494 );
5495 false
5496 }
5497 }
5498
5499 pub fn verify_transaction(
5501 &self,
5502 tx: VersionedTransaction,
5503 verification_mode: TransactionVerificationMode,
5504 ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5505 if !self.feature_set.snapshot().enable_tx_v1
5507 && tx.version() == TransactionVersion::Number(1)
5508 {
5509 return Err(TransactionError::UnsupportedVersion);
5510 }
5511
5512 let serialized_message = tx.message.serialize();
5513 self.verify_transaction_with_serialized_message(tx, &serialized_message, verification_mode)
5514 }
5515
5516 pub fn verify_transaction_with_serialized_message(
5523 &self,
5524 tx: VersionedTransaction,
5525 serialized_message: &[u8],
5526 verification_mode: TransactionVerificationMode,
5527 ) -> Result<RuntimeTransaction<SanitizedTransaction>> {
5528 let enable_tx_v1 = self.feature_set.snapshot().enable_tx_v1;
5530 if !enable_tx_v1 && tx.version() == TransactionVersion::Number(1) {
5531 return Err(TransactionError::UnsupportedVersion);
5532 }
5533 let max_transaction_size = match tx.version() {
5534 TransactionVersion::Number(1) if enable_tx_v1 => {
5535 solana_message::v1::MAX_TRANSACTION_SIZE
5536 }
5537 _ => PACKET_DATA_SIZE,
5538 } as u64;
5539
5540 let sanitized_tx = {
5543 let size =
5544 wincode::serialized_size(&tx).map_err(|_| TransactionError::SanitizeFailure)?;
5545 if size > max_transaction_size {
5546 return Err(TransactionError::SanitizeFailure);
5547 }
5548
5549 if tx.message.instructions().len()
5551 > solana_transaction_context::MAX_INSTRUCTION_TRACE_LENGTH
5552 {
5553 return Err(solana_transaction_error::TransactionError::SanitizeFailure);
5554 }
5555
5556 let message_hash = if verification_mode == TransactionVerificationMode::FullVerification
5557 {
5558 tx.verify_and_hash_message()?
5559 } else {
5560 VersionedMessage::hash_raw_message(serialized_message)
5561 };
5562
5563 RuntimeTransaction::try_create(
5564 tx,
5565 MessageHash::Precomputed(message_hash),
5566 None,
5567 self,
5568 self.get_reserved_account_keys(),
5569 )
5570 }?;
5571
5572 Ok(sanitized_tx)
5573 }
5574
5575 pub fn check_reserved_keys(&self, tx: &impl SVMMessage) -> Result<()> {
5579 let reserved_keys = self.get_reserved_account_keys();
5582 for (index, key) in tx.account_keys().iter().enumerate() {
5583 if tx.is_writable(index) && reserved_keys.contains(key) {
5584 return Err(TransactionError::ResanitizationNeeded);
5585 }
5586 }
5587
5588 Ok(())
5589 }
5590
5591 pub fn calculate_capitalization_for_tests(&self) -> u64 {
5601 self.rc
5602 .accounts
5603 .accounts_db
5604 .calculate_capitalization_at_startup_from_index(&self.ancestors)
5605 }
5606
5607 pub fn set_capitalization_for_tests(&self, capitalization: u64) {
5612 self.capitalization.store(capitalization, Relaxed);
5613 }
5614
5615 pub fn get_snapshot_hash(&self) -> SnapshotHash {
5619 SnapshotHash::new(self.accounts_lt_hash.lock().unwrap().0.checksum())
5620 }
5621
5622 pub fn verify_snapshot_bank(
5625 &self,
5626 skip_shrink: bool,
5627 force_clean: bool,
5628 latest_full_snapshot_slot: Slot,
5629 calculated_accounts_lt_hash: Option<&AccountsLtHash>,
5630 ) -> bool {
5631 let (verified_accounts, verify_accounts_time_us) = measure_us!({
5632 let should_verify_accounts = !self.rc.accounts.accounts_db.skip_initial_hash_calc;
5633 if should_verify_accounts {
5634 self.verify_accounts(calculated_accounts_lt_hash)
5635 } else {
5636 info!("Verifying accounts... Skipped.");
5637 true
5638 }
5639 });
5640
5641 let (_, clean_time_us) = measure_us!({
5642 let should_clean = force_clean || (!skip_shrink && self.slot() > 0);
5643 if should_clean {
5644 info!("Cleaning...");
5645 self.rc
5650 .accounts
5651 .accounts_db
5652 .clean_accounts(Some(latest_full_snapshot_slot), true);
5653 info!("Cleaning... Done.");
5654 } else {
5655 info!("Cleaning... Skipped.");
5656 }
5657 });
5658
5659 let (_, shrink_time_us) = measure_us!({
5660 let should_shrink = !skip_shrink && self.slot() > 0;
5661 if should_shrink {
5662 info!("Shrinking...");
5663 self.rc.accounts.accounts_db.shrink_all_slots(
5664 true,
5665 Some(self.slot()),
5667 );
5668 info!("Shrinking... Done.");
5669 } else {
5670 info!("Shrinking... Skipped.");
5671 }
5672 });
5673
5674 info!("Verifying bank...");
5675 let (verified_bank, verify_bank_time_us) = measure_us!(self.verify_hash());
5676 info!("Verifying bank... Done.");
5677
5678 datapoint_info!(
5679 "verify_snapshot_bank",
5680 ("clean_us", clean_time_us, i64),
5681 ("shrink_us", shrink_time_us, i64),
5682 ("verify_accounts_us", verify_accounts_time_us, i64),
5683 ("verify_bank_us", verify_bank_time_us, i64),
5684 );
5685
5686 verified_accounts && verified_bank
5687 }
5688
5689 pub fn hashes_per_tick(&self) -> Option<u64> {
5691 *self.hashes_per_tick.read().unwrap()
5692 }
5693
5694 pub fn ticks_per_slot(&self) -> u64 {
5696 self.ticks_per_slot
5697 }
5698
5699 pub fn ticks_per_second(&self) -> u64 {
5701 let ticks_per_slot = u128::from(self.ticks_per_slot.max(1));
5702 let ns_per_tick = self.ns_per_slot.saturating_div(ticks_per_slot).max(1);
5703 u64::try_from(1_000_000_000u128.saturating_div(ns_per_tick))
5704 .expect("ticks per second must fit in u64")
5705 }
5706
5707 pub fn slots_per_year(&self) -> f64 {
5709 self.slots_per_year
5710 }
5711
5712 pub fn tick_height(&self) -> u64 {
5714 self.tick_height.load(Relaxed)
5715 }
5716
5717 pub fn inflation(&self) -> Inflation {
5719 *self.inflation.read().unwrap()
5720 }
5721
5722 pub fn rent_collector(&self) -> &RentCollector {
5724 &self.rent_collector
5725 }
5726
5727 pub fn capitalization(&self) -> u64 {
5729 self.capitalization.load(Relaxed)
5730 }
5731
5732 pub fn max_tick_height(&self) -> u64 {
5734 self.max_tick_height
5735 }
5736
5737 pub fn block_height(&self) -> u64 {
5739 self.block_height
5740 }
5741
5742 pub fn get_slots_in_epoch(&self, epoch: Epoch) -> u64 {
5744 self.epoch_schedule().get_slots_in_epoch(epoch)
5745 }
5746
5747 pub fn get_leader_schedule_epoch(&self, slot: Slot) -> Epoch {
5750 self.epoch_schedule().get_leader_schedule_epoch(slot)
5751 }
5752
5753 fn update_stakes_cache(
5755 &self,
5756 txs: &[impl SVMMessage],
5757 processing_results: &[TransactionProcessingResult],
5758 ) {
5759 debug_assert_eq!(txs.len(), processing_results.len());
5760 let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
5761 let use_fixed_point_stake_math = self.use_fixed_point_stake_math();
5762 txs.iter()
5763 .zip(processing_results)
5764 .filter_map(|(tx, processing_result)| {
5765 processing_result
5766 .processed_transaction()
5767 .map(|processed_tx| (tx, processed_tx))
5768 })
5769 .filter_map(|(tx, processed_tx)| {
5770 processed_tx
5771 .executed_transaction()
5772 .map(|executed_tx| (tx, executed_tx))
5773 })
5774 .filter(|(_, executed_tx)| executed_tx.was_successful())
5775 .flat_map(|(tx, executed_tx)| {
5776 let num_account_keys = tx.account_keys().len();
5777 let loaded_tx = &executed_tx.loaded_transaction;
5778 loaded_tx.accounts.iter().take(num_account_keys)
5779 })
5780 .for_each(|(pubkey, account)| {
5781 self.stakes_cache.check_and_store(
5784 pubkey,
5785 account,
5786 new_warmup_cooldown_rate_epoch,
5787 use_fixed_point_stake_math,
5788 );
5789 });
5790 }
5791
5792 pub fn vote_accounts(&self) -> Arc<VoteAccountsHashMap> {
5795 let stakes = self.stakes_cache.stakes();
5796 Arc::from(stakes.vote_accounts())
5797 }
5798
5799 pub fn get_vote_account(&self, vote_account: &Pubkey) -> Option<VoteAccount> {
5801 let stakes = self.stakes_cache.stakes();
5802 let vote_account = stakes.vote_accounts().get(vote_account)?;
5803 Some(vote_account.clone())
5804 }
5805
5806 pub fn current_epoch_stakes(&self) -> &VersionedEpochStakes {
5808 self.epoch_stakes
5811 .get(&self.epoch.saturating_add(1))
5812 .expect("Current epoch stakes must exist")
5813 }
5814
5815 pub fn epoch_stakes(&self, epoch: Epoch) -> Option<&VersionedEpochStakes> {
5817 self.epoch_stakes.get(&epoch)
5818 }
5819
5820 pub fn verify_certificate(
5822 &self,
5823 cert: UnverifiedCertificate,
5824 ) -> std::result::Result<Certificate, CertVerifyError> {
5825 let slot = cert.cert_type.slot();
5826 let epoch_stakes = self
5827 .epoch_stakes_from_slot(slot)
5828 .ok_or(CertVerifyError::MissingRankMap)?;
5829 let key_to_rank_map = epoch_stakes.bls_pubkey_to_rank_map();
5830 let total_stake = key_to_rank_map.total_stake();
5831
5832 let cert =
5833 cert_verify::verify_certificate(cert, key_to_rank_map.len(), total_stake, |rank| {
5834 key_to_rank_map
5835 .get_pubkey_stake_entry(rank)
5836 .map(|entry| (entry.stake, entry.bls_pubkey))
5837 })?;
5838
5839 Ok(cert)
5840 }
5841
5842 pub fn epoch_stakes_map(&self) -> &HashMap<Epoch, VersionedEpochStakes> {
5843 &self.epoch_stakes
5844 }
5845
5846 pub fn current_epoch_staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
5848 self.current_epoch_stakes().stakes().staked_nodes()
5849 }
5850
5851 pub fn epoch_staked_nodes(&self, epoch: Epoch) -> Option<Arc<HashMap<Pubkey, u64>>> {
5853 Some(self.epoch_stakes.get(&epoch)?.stakes().staked_nodes())
5854 }
5855
5856 pub fn epoch_total_stake(&self, epoch: Epoch) -> Option<u64> {
5858 self.epoch_stakes
5859 .get(&epoch)
5860 .map(|epoch_stakes| epoch_stakes.total_stake())
5861 }
5862
5863 pub fn get_current_epoch_total_stake(&self) -> u64 {
5865 self.current_epoch_stakes().total_stake()
5866 }
5867
5868 pub fn epoch_vote_accounts(&self, epoch: Epoch) -> Option<&VoteAccountsHashMap> {
5870 let epoch_stakes = self.epoch_stakes.get(&epoch)?.stakes();
5871 Some(epoch_stakes.vote_accounts().as_ref())
5872 }
5873
5874 pub fn get_current_epoch_vote_accounts(&self) -> &VoteAccountsHashMap {
5876 self.current_epoch_stakes()
5877 .stakes()
5878 .vote_accounts()
5879 .as_ref()
5880 }
5881
5882 pub fn epoch_authorized_voter(&self, vote_account: &Pubkey) -> Option<&Pubkey> {
5885 self.epoch_stakes
5886 .get(&self.epoch)
5887 .expect("Epoch stakes for bank's own epoch must exist")
5888 .epoch_authorized_voters()
5889 .get(vote_account)
5890 }
5891
5892 pub fn epoch_vote_accounts_for_node_id(&self, node_id: &Pubkey) -> Option<&NodeVoteAccounts> {
5895 self.epoch_stakes
5896 .get(&self.epoch)
5897 .expect("Epoch stakes for bank's own epoch must exist")
5898 .node_id_to_vote_accounts()
5899 .get(node_id)
5900 }
5901
5902 pub fn epoch_node_id_to_stake(&self, epoch: Epoch, node_id: &Pubkey) -> Option<u64> {
5904 self.epoch_stakes(epoch)
5905 .and_then(|epoch_stakes| epoch_stakes.node_id_to_stake(node_id))
5906 }
5907
5908 pub fn total_epoch_stake(&self) -> u64 {
5910 self.epoch_stakes
5911 .get(&self.epoch)
5912 .expect("Epoch stakes for bank's own epoch must exist")
5913 .total_stake()
5914 }
5915
5916 pub fn epoch_vote_account_stake(&self, vote_account: &Pubkey) -> u64 {
5918 *self
5919 .epoch_vote_accounts(self.epoch())
5920 .expect("Bank epoch vote accounts must contain entry for the bank's own epoch")
5921 .get(vote_account)
5922 .map(|(stake, _)| stake)
5923 .unwrap_or(&0)
5924 }
5925
5926 pub fn get_epoch_and_slot_index(&self, slot: Slot) -> (Epoch, SlotIndex) {
5932 self.epoch_schedule().get_epoch_and_slot_index(slot)
5933 }
5934
5935 pub fn get_epoch_info(&self) -> EpochInfo {
5936 let absolute_slot = self.slot();
5937 let block_height = self.block_height();
5938 let (epoch, slot_index) = self.get_epoch_and_slot_index(absolute_slot);
5939 let slots_in_epoch = self.get_slots_in_epoch(epoch);
5940 let transaction_count = Some(self.transaction_count());
5941 EpochInfo {
5942 epoch,
5943 slot_index,
5944 slots_in_epoch,
5945 absolute_slot,
5946 block_height,
5947 transaction_count,
5948 }
5949 }
5950
5951 pub fn is_empty(&self) -> bool {
5952 !self.is_delta.load(Relaxed)
5953 }
5954
5955 pub fn add_mockup_builtin(&mut self, program_id: Pubkey, builtin: BuiltinFunctionRegisterer) {
5956 self.add_builtin(
5957 program_id,
5958 "mockup",
5959 ProgramCacheEntry::new_builtin(self.slot, builtin),
5960 );
5961 }
5962
5963 pub fn add_precompile(&mut self, program_id: &Pubkey) {
5964 debug!("Adding precompiled program {program_id}");
5965 self.add_precompiled_account(program_id);
5966 debug!("Added precompiled program {program_id:?}");
5967 }
5968
5969 pub(crate) fn clean_accounts(&self) {
5974 let highest_slot_to_clean = self.slot().saturating_sub(1);
5981
5982 self.rc
5983 .accounts
5984 .accounts_db
5985 .clean_accounts(Some(highest_slot_to_clean), false);
5986 }
5987
5988 pub fn print_accounts_stats(&self) {
5989 self.rc.accounts.accounts_db.print_accounts_stats("");
5990 }
5991
5992 pub fn shrink_candidate_slots(&self) -> usize {
5993 self.rc
5994 .accounts
5995 .accounts_db
5996 .shrink_candidate_slots(self.epoch_schedule())
5997 }
5998
5999 pub(crate) fn shrink_ancient_slots(&self) {
6000 self.rc
6001 .accounts
6002 .accounts_db
6003 .shrink_ancient_slots(self.epoch_schedule())
6004 }
6005
6006 pub fn read_cost_tracker(&self) -> LockResult<RwLockReadGuard<'_, CostTracker>> {
6007 self.cost_tracker.read()
6008 }
6009
6010 pub fn write_cost_tracker(&self) -> LockResult<RwLockWriteGuard<'_, CostTracker>> {
6011 self.cost_tracker.write()
6012 }
6013
6014 pub fn should_bank_still_be_processing_txs(
6017 bank_creation_time: &Instant,
6018 max_tx_ingestion_nanos: u128,
6019 ) -> bool {
6020 bank_creation_time.elapsed().as_nanos() <= max_tx_ingestion_nanos
6022 }
6023
6024 pub fn deactivate_feature(&mut self, id: &Pubkey) {
6025 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6026 feature_set.deactivate(id);
6027 self.feature_set = Arc::new(feature_set);
6028 self.refresh_slot_params();
6029 }
6030
6031 pub fn activate_feature(&mut self, id: &Pubkey) {
6032 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6033 feature_set.activate(id, 0);
6034 self.feature_set = Arc::new(feature_set);
6035 self.refresh_slot_params();
6036 }
6037
6038 pub fn fill_bank_with_ticks_for_tests(&self) {
6039 self.do_fill_bank_with_ticks_for_tests(&BankWithScheduler::no_scheduler_available())
6040 }
6041
6042 pub(crate) fn do_fill_bank_with_ticks_for_tests(&self, scheduler: &InstalledSchedulerRwLock) {
6043 if self.tick_height.load(Relaxed) < self.max_tick_height {
6044 let last_blockhash = self.last_blockhash();
6045 while self.last_blockhash() == last_blockhash {
6046 self.register_tick(&Hash::new_unique(), scheduler)
6047 }
6048 } else {
6049 warn!("Bank already reached max tick height, cannot fill it with more ticks");
6050 }
6051 }
6052
6053 pub fn get_reserved_account_keys(&self) -> &HashSet<Pubkey> {
6056 &self.reserved_account_keys.active
6057 }
6058
6059 fn initialize_after_snapshot_restore<F, TP>(&mut self, rewards_thread_pool_builder: F)
6062 where
6063 F: FnOnce() -> TP,
6064 TP: std::borrow::Borrow<ThreadPool>,
6065 {
6066 self.transaction_processor =
6067 TransactionBatchProcessor::new_uninitialized(self.slot, self.epoch);
6068 if let Some(compute_budget) = &self.compute_budget {
6069 self.transaction_processor
6070 .set_execution_cost(compute_budget.to_cost());
6071 }
6072
6073 self.compute_and_apply_features_after_snapshot_restore();
6074 self.stakes_cache.refresh_delegated_stakes(
6075 self.new_warmup_cooldown_rate_epoch(),
6076 self.use_fixed_point_stake_math(),
6077 );
6078
6079 self.recalculate_partitioned_rewards_if_active(rewards_thread_pool_builder);
6080
6081 self.transaction_processor
6082 .fill_missing_sysvar_cache_entries(self);
6083 }
6084
6085 fn compute_and_apply_genesis_features(&mut self) {
6087 let feature_set = self.compute_active_feature_set(false).0;
6089 self.feature_set = Arc::new(feature_set);
6090
6091 if self
6094 .feature_set
6095 .snapshot()
6096 .deprecate_rent_exemption_threshold
6097 {
6098 self.rent_collector.deprecate_rent_exemption_threshold();
6099 }
6100
6101 if self
6105 .feature_set
6106 .is_active(&feature_set::double_disinflation_rate::id())
6107 {
6108 self.apply_double_disinflation_rate();
6109 }
6110
6111 self.add_builtin_program_accounts();
6113
6114 self.apply_activated_features();
6115 }
6116
6117 fn apply_double_disinflation_rate(&mut self) {
6120 let year = self.slot_in_year_for_inflation();
6121 let mut inflation = *self.inflation.read().unwrap();
6122 let anchor_rate = inflation.total(year);
6123 let taper = feature_set::double_disinflation_rate::TAPER;
6124 inflation.taper = taper;
6125 inflation.initial = anchor_rate / (1.0 - taper).powf(year);
6126 self.inflation = Arc::new(RwLock::new(inflation));
6130 }
6131
6132 fn compute_and_apply_features_after_snapshot_restore(&mut self) {
6135 let feature_set = self.compute_active_feature_set(false).0;
6137 self.feature_set = Arc::new(feature_set);
6138
6139 self.apply_activated_features();
6140 self.assert_bank_matches_slot_params();
6141 }
6142
6143 fn compute_and_apply_new_feature_activations(&mut self) {
6145 let include_pending = true;
6146 let (feature_set, new_feature_activations) =
6147 self.compute_active_feature_set(include_pending);
6148 self.feature_set = Arc::new(feature_set);
6149 self.refresh_slot_params();
6150
6151 for feature_id in new_feature_activations.iter() {
6153 if let Some(mut account) = self.get_account_with_fixed_root(feature_id)
6154 && let Some(mut feature) = feature::state::from_account(&account)
6155 {
6156 feature.activated_at = Some(self.slot());
6157 if feature::state::to_account(&feature, &mut account).is_some() {
6158 self.store_account(feature_id, &account);
6159 }
6160 info!("Feature {} activated at slot {}", feature_id, self.slot());
6161 }
6162 }
6163
6164 self.reserved_account_keys = {
6166 let mut reserved_keys = ReservedAccountKeys::clone(&self.reserved_account_keys);
6167 reserved_keys.update_active_set(&self.feature_set);
6168 Arc::new(reserved_keys)
6169 };
6170
6171 if new_feature_activations.contains(&feature_set::deprecate_rent_exemption_threshold::id())
6172 {
6173 self.rent_collector.deprecate_rent_exemption_threshold();
6174 self.update_rent();
6175 }
6176
6177 let rent_feature_gates = [
6183 (
6184 feature_set::set_lamports_per_byte_to_6333::id(),
6185 feature_set::set_lamports_per_byte_to_6333::LAMPORTS_PER_BYTE,
6186 ),
6187 (
6188 feature_set::set_lamports_per_byte_to_5080::id(),
6189 feature_set::set_lamports_per_byte_to_5080::LAMPORTS_PER_BYTE,
6190 ),
6191 (
6192 feature_set::set_lamports_per_byte_to_2575::id(),
6193 feature_set::set_lamports_per_byte_to_2575::LAMPORTS_PER_BYTE,
6194 ),
6195 (
6196 feature_set::set_lamports_per_byte_to_1322::id(),
6197 feature_set::set_lamports_per_byte_to_1322::LAMPORTS_PER_BYTE,
6198 ),
6199 (
6200 feature_set::set_lamports_per_byte_to_696::id(),
6201 feature_set::set_lamports_per_byte_to_696::LAMPORTS_PER_BYTE,
6202 ),
6203 ];
6204 for (feature_id, lamports_per_byte) in rent_feature_gates {
6205 if new_feature_activations.contains(&feature_id) {
6206 self.rent_collector.rent.lamports_per_byte = lamports_per_byte;
6207 self.update_rent();
6208 }
6209 }
6210
6211 if new_feature_activations.contains(&feature_set::set_lamports_per_byte_to_6960::id()) {
6216 self.rent_collector.rent.lamports_per_byte =
6217 feature_set::set_lamports_per_byte_to_6960::LAMPORTS_PER_BYTE;
6218 self.update_rent();
6219 }
6220
6221 if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
6222 *self.inflation.write().unwrap() = Inflation::pico();
6223 self.fee_rate_governor.burn_percent = solana_fee_calculator::DEFAULT_BURN_PERCENT;
6224 }
6225
6226 if !new_feature_activations.is_disjoint(&self.feature_set.full_inflation_features_enabled())
6227 {
6228 *self.inflation.write().unwrap() = Inflation::full();
6229 self.fee_rate_governor.burn_percent = solana_fee_calculator::DEFAULT_BURN_PERCENT;
6230 }
6231
6232 if new_feature_activations.contains(&feature_set::double_disinflation_rate::id()) {
6233 self.apply_double_disinflation_rate();
6234 }
6235
6236 self.apply_slot_time_persistent_changes();
6238 self.apply_slot_time_runtime_changes();
6239
6240 self.apply_new_builtin_program_feature_transitions(&new_feature_activations);
6241
6242 if new_feature_activations.contains(&feature_set::replace_spl_token_with_p_token::id())
6243 && let Err(e) = self.upgrade_loader_v2_program_with_loader_v3_program(
6244 &feature_set::replace_spl_token_with_p_token::SPL_TOKEN_PROGRAM_ID,
6245 &feature_set::replace_spl_token_with_p_token::PTOKEN_PROGRAM_BUFFER,
6246 self.feature_set
6247 .snapshot()
6248 .relax_programdata_account_check_migration,
6249 "replace_spl_token_with_p_token",
6250 )
6251 {
6252 warn!(
6253 "Failed to replace SPL Token with p-token buffer '{}': {e}",
6254 feature_set::replace_spl_token_with_p_token::PTOKEN_PROGRAM_BUFFER,
6255 );
6256 }
6257
6258 if new_feature_activations.contains(&feature_set::upgrade_bpf_stake_program_to_v5::id())
6259 && let Err(e) = self.upgrade_core_bpf_program(
6260 &solana_sdk_ids::stake::id(),
6261 &feature_set::upgrade_bpf_stake_program_to_v5::buffer::id(),
6262 "upgrade_stake_program_to_v5",
6263 )
6264 {
6265 error!("Failed to upgrade Core BPF Stake program: {e}");
6266 }
6267
6268 if new_feature_activations.contains(&feature_set::upgrade_bpf_stake_program_to_v5_1::id())
6269 && let Err(e) = self.upgrade_core_bpf_program(
6270 &solana_sdk_ids::stake::id(),
6271 &feature_set::upgrade_bpf_stake_program_to_v5_1::buffer::id(),
6272 "upgrade_stake_program_to_v5_1",
6273 )
6274 {
6275 error!("Failed to upgrade Core BPF Stake program: {e}");
6276 }
6277 }
6278
6279 fn apply_new_builtin_program_feature_transitions(
6280 &mut self,
6281 new_feature_activations: &AHashSet<Pubkey>,
6282 ) {
6283 for builtin in BUILTINS.iter() {
6284 if let Some(feature_id) = builtin.enable_feature_id
6285 && new_feature_activations.contains(&feature_id)
6286 {
6287 self.add_builtin(
6288 builtin.program_id,
6289 builtin.name,
6290 ProgramCacheEntry::new_builtin(
6291 self.feature_set.activated_slot(&feature_id).unwrap_or(0),
6292 builtin.register_fn,
6293 ),
6294 );
6295 }
6296
6297 if let Some(core_bpf_migration_config) = &builtin.core_bpf_migration_config {
6298 if new_feature_activations.contains(&core_bpf_migration_config.feature_id)
6302 && let Err(e) = self.migrate_builtin_to_core_bpf(
6303 &builtin.program_id,
6304 core_bpf_migration_config,
6305 self.feature_set
6306 .snapshot()
6307 .relax_programdata_account_check_migration,
6308 )
6309 {
6310 warn!(
6311 "Failed to migrate builtin {} to Core BPF: {}",
6312 builtin.name, e
6313 );
6314 }
6315 };
6316 }
6317
6318 for stateless_builtin in STATELESS_BUILTINS.iter() {
6322 if let Some(core_bpf_migration_config) = &stateless_builtin.core_bpf_migration_config
6323 && new_feature_activations.contains(&core_bpf_migration_config.feature_id)
6324 && let Err(e) = self.migrate_builtin_to_core_bpf(
6325 &stateless_builtin.program_id,
6326 core_bpf_migration_config,
6327 self.feature_set
6328 .snapshot()
6329 .relax_programdata_account_check_migration,
6330 )
6331 {
6332 warn!(
6333 "Failed to migrate stateless builtin {} to Core BPF: {}",
6334 stateless_builtin.name, e
6335 );
6336 }
6337 }
6338
6339 for precompile in get_precompiles() {
6340 if let Some(feature_id) = &precompile.feature
6341 && new_feature_activations.contains(feature_id)
6342 {
6343 self.add_precompile(&precompile.program_id);
6344 }
6345 }
6346 }
6347
6348 fn adjust_sysvar_balance_for_rent(&self, account: &mut AccountSharedData) {
6349 account.set_lamports(
6350 self.get_minimum_balance_for_rent_exemption(account.data().len())
6351 .max(account.lamports()),
6352 );
6353 }
6354
6355 fn compute_active_feature_set(&self, include_pending: bool) -> (FeatureSet, AHashSet<Pubkey>) {
6358 let mut active = self.feature_set.active().clone();
6359 let mut inactive = AHashSet::new();
6360 let mut pending = AHashSet::new();
6361 let slot = self.slot();
6362
6363 for feature_id in self.feature_set.inactive() {
6364 let mut activated = None;
6365 if let Some(account) = self.get_account_with_fixed_root(feature_id)
6366 && let Some(feature) = feature::state::from_account(&account)
6367 {
6368 match feature.activated_at {
6369 None if include_pending => {
6370 pending.insert(*feature_id);
6372 activated = Some(slot);
6373 }
6374 Some(activation_slot) if slot >= activation_slot => {
6375 activated = Some(activation_slot);
6377 }
6378 _ => {}
6379 }
6380 }
6381 if let Some(slot) = activated {
6382 active.insert(*feature_id, slot);
6383 } else {
6384 inactive.insert(*feature_id);
6385 }
6386 }
6387
6388 (FeatureSet::new(active, inactive), pending)
6389 }
6390
6391 pub fn compute_pending_activation_slot(&self, feature_id: &Pubkey) -> Option<Slot> {
6394 let account = self.get_account_with_fixed_root(feature_id)?;
6395 let feature = feature::from_account(&account)?;
6396 if feature.activated_at.is_some() {
6397 return None;
6399 }
6400 let active_epoch = self.epoch + 1;
6402 Some(self.epoch_schedule.get_first_slot_in_epoch(active_epoch))
6403 }
6404
6405 fn add_active_builtin_programs(&mut self) {
6406 for builtin in BUILTINS.iter() {
6407 let builtin_is_bpf = builtin.core_bpf_migration_config.is_some() && {
6424 self.get_account(&builtin.program_id)
6425 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
6426 .unwrap_or(false)
6427 };
6428
6429 if builtin_is_bpf {
6432 continue;
6433 }
6434
6435 let builtin_is_active = builtin
6436 .enable_feature_id
6437 .map(|feature_id| self.feature_set.is_active(&feature_id))
6438 .unwrap_or(true);
6439
6440 if builtin_is_active {
6441 let activation_slot = builtin
6442 .enable_feature_id
6443 .and_then(|feature_id| self.feature_set.activated_slot(&feature_id))
6444 .unwrap_or(0);
6445 self.transaction_processor.add_builtin(
6446 builtin.program_id,
6447 ProgramCacheEntry::new_builtin(activation_slot, builtin.register_fn),
6448 );
6449 }
6450 }
6451 }
6452
6453 fn add_builtin_program_accounts(&mut self) {
6454 for builtin in BUILTINS.iter() {
6455 let builtin_is_bpf = builtin.core_bpf_migration_config.is_some() && {
6472 self.get_account(&builtin.program_id)
6473 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
6474 .unwrap_or(false)
6475 };
6476
6477 if builtin_is_bpf {
6480 continue;
6481 }
6482
6483 let builtin_is_active = builtin
6484 .enable_feature_id
6485 .map(|feature_id| self.feature_set.is_active(&feature_id))
6486 .unwrap_or(true);
6487
6488 if builtin_is_active {
6489 self.add_builtin_account(builtin.name, &builtin.program_id);
6490 }
6491 }
6492
6493 for precompile in get_precompiles() {
6494 let precompile_is_active = precompile
6495 .feature
6496 .as_ref()
6497 .map(|feature_id| self.feature_set.is_active(feature_id))
6498 .unwrap_or(true);
6499
6500 if precompile_is_active {
6501 self.add_precompile(&precompile.program_id);
6502 }
6503 }
6504 }
6505
6506 pub fn calculate_accounts_data_size(&self) -> ScanResult<u64> {
6514 let mut accounts_data_size: u64 = 0;
6515 self.scan_all_accounts(|address_account_slot| {
6516 let Some((_address, account, _slot)) = address_account_slot else {
6517 return;
6518 };
6519 accounts_data_size = accounts_data_size
6520 .checked_add(account.data().len() as u64)
6521 .expect("accounts data size cannot overflow");
6522 })?;
6523 Ok(accounts_data_size)
6524 }
6525
6526 pub fn is_in_slot_hashes_history(&self, slot: &Slot) -> bool {
6527 if slot < &self.slot
6528 && let Ok(slot_hashes) = self.transaction_processor.sysvar_cache().get_slot_hashes()
6529 {
6530 return slot_hashes.get(slot).is_some();
6531 }
6532 false
6533 }
6534
6535 pub fn fee_structure(&self) -> &FeeStructure {
6536 &self.fee_structure
6537 }
6538
6539 pub fn parent_block_id(&self) -> Option<Hash> {
6540 self.parent().and_then(|p| p.block_id())
6541 }
6542
6543 pub fn block_id(&self) -> Option<Hash> {
6544 *self.block_id.read().unwrap()
6545 }
6546
6547 pub fn set_block_id(&self, block_id: Option<Hash>) {
6548 let mut block_id_w = self.block_id.write().unwrap();
6549 debug_assert!(block_id_w.is_none() || *block_id_w == block_id);
6550 *block_id_w = block_id
6551 }
6552
6553 pub fn compute_budget(&self) -> Option<ComputeBudget> {
6554 self.compute_budget
6555 }
6556
6557 pub fn add_builtin(&self, program_id: Pubkey, name: &str, builtin: ProgramCacheEntry) {
6558 debug!("Adding program {name} under {program_id:?}");
6559 self.add_builtin_account(name, &program_id);
6560 self.transaction_processor.add_builtin(program_id, builtin);
6561 debug!("Added program {name} under {program_id:?}");
6562 }
6563
6564 fn add_builtin_account(&self, name: &str, program_id: &Pubkey) {
6567 let existing_genuine_program =
6568 self.get_account_with_fixed_root(program_id)
6569 .and_then(|account| {
6570 if native_loader::check_id(account.owner()) {
6574 Some(account)
6575 } else {
6576 self.burn_and_purge_account(program_id, account);
6578 None
6579 }
6580 });
6581
6582 if existing_genuine_program.is_some() {
6584 return;
6586 }
6587
6588 assert!(
6589 !self.freeze_started(),
6590 "Can't change frozen bank by adding not-existing new builtin program ({name}, \
6591 {program_id}). Maybe, inconsistent program activation is detected on snapshot \
6592 restore?"
6593 );
6594
6595 let (lamports, rent_epoch) =
6597 self.inherit_specially_retained_account_fields(&existing_genuine_program);
6598 let account: AccountSharedData = AccountSharedData::from(Account {
6599 lamports,
6600 data: name.as_bytes().to_vec(),
6601 owner: solana_sdk_ids::native_loader::id(),
6602 executable: true,
6603 rent_epoch,
6604 });
6605 self.store_account_and_update_capitalization(program_id, &account);
6606 }
6607
6608 pub fn get_bank_hash_stats(&self) -> BankHashStats {
6609 self.bank_hash_stats.load()
6610 }
6611
6612 pub fn clear_epoch_rewards_cache(&self) {
6613 self.epoch_rewards_calculation_cache.lock().unwrap().clear();
6614 }
6615
6616 pub fn set_accounts_lt_hash_for_snapshot_minimizer(&self, accounts_lt_hash: AccountsLtHash) {
6618 *self.accounts_lt_hash.lock().unwrap() = accounts_lt_hash;
6619 }
6620
6621 pub fn get_collector_fee_details(&self) -> CollectorFeeDetails {
6623 self.collector_fee_details.read().unwrap().clone()
6624 }
6625
6626 pub fn minimum_vote_account_balance_for_vat(&self) -> u64 {
6630 let vote_account_rent_exempt_minimum = self
6631 .rent_collector
6632 .rent
6633 .minimum_balance(VoteStateV4::size_of());
6634 if self.feature_set.snapshot().alpenglow {
6635 vote_account_rent_exempt_minimum + self.vat_to_burn_per_epoch()
6636 } else {
6637 vote_account_rent_exempt_minimum
6638 }
6639 }
6640
6641 pub fn get_top_epoch_stakes(&self) -> Stakes<StakeAccount<Delegation>> {
6644 self.stakes_cache.stakes().clone_and_filter_for_vat(
6645 MAX_ALPENGLOW_VOTE_ACCOUNTS,
6646 self.minimum_vote_account_balance_for_vat(),
6647 )
6648 }
6649
6650 pub fn calculate_and_set_block_id_for_dcou(bank: &Bank) {
6662 if bank.block_id().is_some() {
6663 return;
6665 }
6666
6667 let Some(parent) = bank.parent() else {
6668 bank.freeze();
6672 bank.set_block_id(Some(bank.hash()));
6673 return;
6674 };
6675
6676 let parent_block_id = parent.block_id().unwrap_or_else(|| {
6677 Self::calculate_and_set_block_id_for_dcou(&parent);
6679 parent.block_id().unwrap()
6680 });
6681
6682 bank.freeze();
6684 let block_id =
6685 solana_sha256_hasher::hashv(&[parent_block_id.as_ref(), bank.hash().as_ref()]);
6686 bank.set_block_id(Some(block_id));
6687 }
6688
6689 pub(crate) fn get_alpenglow_migration_slot(&self) -> Option<Slot> {
6690 let genesis_cert = self.get_alpenglow_genesis_certificate()?;
6691 Some(genesis_cert.block.slot)
6692 }
6693
6694 pub fn set_accounts_lt_hash_async_progress_is_at_end(&self) {
6697 self.accounts_lt_hash_async_progress.set_is_at_end_of_slot();
6698 }
6699
6700 pub fn clear_accounts_lt_hash_async_progress_is_at_end(&self) {
6704 self.accounts_lt_hash_async_progress
6705 .clear_is_at_end_of_slot();
6706 }
6707}
6708
6709impl InvokeContextCallback for Bank {
6710 fn get_epoch_stake(&self) -> u64 {
6711 self.get_current_epoch_total_stake()
6712 }
6713
6714 fn get_epoch_stake_for_vote_account(&self, vote_address: &Pubkey) -> u64 {
6715 self.get_current_epoch_vote_accounts()
6716 .get(vote_address)
6717 .map(|(stake, _)| *stake)
6718 .unwrap_or(0)
6719 }
6720
6721 fn is_precompile(&self, program_id: &Pubkey) -> bool {
6722 is_precompile(program_id, |feature_id: &Pubkey| {
6723 self.feature_set.is_active(feature_id)
6724 })
6725 }
6726
6727 fn process_precompile(
6728 &self,
6729 program_id: &Pubkey,
6730 data: &[u8],
6731 instruction_datas: Vec<&[u8]>,
6732 ) -> std::result::Result<(), PrecompileError> {
6733 if let Some(precompile) = get_precompile(program_id, |feature_id: &Pubkey| {
6734 self.feature_set.is_active(feature_id)
6735 }) {
6736 precompile.verify(data, &instruction_datas, &self.feature_set)
6737 } else {
6738 Err(PrecompileError::InvalidPublicKey)
6739 }
6740 }
6741}
6742
6743impl TransactionProcessingCallback for Bank {
6744 fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
6745 self.rc
6746 .accounts
6747 .load_with_fixed_root(&self.ancestors, pubkey)
6748 }
6749
6750 fn inspect_account(&self, _address: &Pubkey, _account_state: AccountState, _is_writable: bool) {
6751 }
6753}
6754
6755impl fmt::Debug for Bank {
6756 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6757 f.debug_struct("Bank")
6758 .field("slot", &self.slot)
6759 .field("bank_id", &self.bank_id)
6760 .field("block_height", &self.block_height)
6761 .field("parent_slot", &self.parent_slot)
6762 .field("capitalization", &self.capitalization())
6763 .finish_non_exhaustive()
6764 }
6765}
6766
6767#[cfg(feature = "dev-context-only-utils")]
6768impl Bank {
6769 fn new_from_fields_for_tests(
6776 bank_rc: BankRc,
6777 fields: BankFieldsToDeserialize,
6778 feature_set: FeatureSet,
6779 epoch_stakes: HashMap<Epoch, VersionedEpochStakes>,
6780 leader: SlotLeader,
6781 stakes_cache: StakesCache,
6782 accounts_data_size_initial: u64,
6783 ) -> Self {
6784 let slot = fields.slot;
6785 let epoch = fields.epoch_schedule.get_epoch(slot);
6786 let ancestors = Ancestors::from(vec![slot]);
6787 let rent = Self::load_rent_from_account_for_snapshot_load(&bank_rc.accounts, &ancestors);
6788
6789 let accounts = Accounts::new(Arc::clone(&bank_rc.accounts.accounts_db));
6790 let mut bank = Self::default_with_accounts(accounts);
6791
6792 bank.rc = bank_rc;
6793 bank.blockhash_queue = RwLock::new(fields.blockhash_queue);
6794 bank.ancestors = ancestors;
6795 bank.hash = RwLock::new(fields.hash);
6796 bank.parent_hash = fields.parent_hash;
6797 bank.parent_slot = fields.parent_slot;
6798 bank.hard_forks = Arc::new(RwLock::new(fields.hard_forks));
6799 bank.transaction_count = AtomicU64::new(fields.transaction_count);
6800 bank.tick_height = AtomicU64::new(fields.tick_height);
6801 bank.signature_count = AtomicU64::new(fields.signature_count);
6802 bank.capitalization = AtomicU64::new(fields.capitalization);
6803 bank.max_tick_height = fields.max_tick_height;
6804 bank.hashes_per_tick = RwLock::new(fields.hashes_per_tick);
6805 bank.ticks_per_slot = fields.ticks_per_slot;
6806 bank.ns_per_slot = fields.ns_per_slot;
6807 bank.genesis_creation_time = fields.genesis_creation_time;
6808 bank.slots_per_year = fields.slots_per_year;
6809 bank.slot = slot;
6810 bank.epoch = epoch;
6811 bank.block_height = fields.block_height;
6812 bank.leader = leader;
6813 bank.fee_rate_governor = fields.fee_rate_governor;
6814 bank.rent_collector = RentCollector::new(
6815 epoch,
6816 fields.epoch_schedule.clone(),
6817 fields.slots_per_year,
6818 rent,
6819 );
6820 bank.epoch_schedule = fields.epoch_schedule;
6821 bank.inflation = Arc::new(RwLock::new(fields.inflation));
6822 bank.stakes_cache = stakes_cache;
6823 bank.epoch_stakes = epoch_stakes;
6824 bank.is_delta = AtomicBool::new(fields.is_delta);
6825 bank.cluster_type = Some(ClusterType::Development);
6826 bank.feature_set = Arc::new(feature_set);
6827 bank.freeze_started = AtomicBool::new(fields.hash != Hash::default());
6828 bank.accounts_data_size_initial = accounts_data_size_initial;
6829 bank.transaction_processor = TransactionBatchProcessor::new_uninitialized(slot, epoch);
6830 bank.accounts_lt_hash = Mutex::new(fields.accounts_lt_hash);
6831 bank.bank_hash_stats = AtomicBankHashStats::new(&fields.bank_hash_stats);
6832 bank.refresh_slot_params_with_baseline(SlotParams::genesis_baseline(
6833 bank.ns_per_slot,
6834 bank.slots_per_year,
6835 bank.hashes_per_tick(),
6836 bank.partitioned_rewards_stake_account_stores_per_block,
6837 ));
6838
6839 bank
6840 }
6841
6842 pub fn new_for_txn_tests(
6853 bank_rc: BankRc,
6854 fields: BankFieldsToDeserialize,
6855 feature_set: FeatureSet,
6856 epoch_stakes: HashMap<Epoch, VersionedEpochStakes>,
6857 ) -> Self {
6858 let leader = SlotLeader {
6859 id: fields.leader_id,
6860 vote_address: Pubkey::default(),
6861 };
6862 let mut bank = Self::new_from_fields_for_tests(
6863 bank_rc,
6864 fields,
6865 feature_set,
6866 epoch_stakes,
6867 leader,
6868 StakesCache::default(), 0, );
6871
6872 bank.apply_activated_features();
6873 bank.transaction_processor
6874 .fill_missing_sysvar_cache_entries(&bank);
6875
6876 bank
6877 }
6878
6879 pub fn new_for_block_tests(
6889 bank_rc: BankRc,
6890 fields: BankFieldsToDeserialize,
6891 feature_set: FeatureSet,
6892 epoch_stakes: HashMap<Epoch, VersionedEpochStakes>,
6893 stakes: Stakes<StakeAccount<Delegation>>,
6894 accounts_data_size_initial: u64,
6895 ) -> Self {
6896 let parent_epoch = fields.epoch_schedule.get_epoch(fields.parent_slot);
6897 let parent_capitalization = fields.capitalization;
6898 let leader =
6899 Self::slot_leader_from_epoch_stakes(fields.slot, &fields.epoch_schedule, &epoch_stakes);
6900
6901 let mut bank = Self::new_from_fields_for_tests(
6902 bank_rc,
6903 fields,
6904 feature_set,
6905 epoch_stakes,
6906 leader,
6907 StakesCache::new(stakes),
6908 accounts_data_size_initial,
6909 );
6910
6911 bank.apply_activated_features();
6912 bank.stakes_cache.refresh_delegated_stakes(
6913 bank.new_warmup_cooldown_rate_epoch(),
6914 bank.use_fixed_point_stake_math(),
6915 );
6916
6917 bank.recalculate_partitioned_rewards_if_active(|| {
6920 rayon::ThreadPoolBuilder::new()
6921 .num_threads(1)
6922 .build()
6923 .expect("single-threaded rayon pool")
6924 });
6925
6926 bank.prepare_for_block_execution(
6927 parent_epoch,
6928 bank.parent_slot,
6929 parent_capitalization,
6930 bank.block_height.saturating_sub(1),
6931 null_tracer(),
6932 );
6933
6934 bank
6935 }
6936
6937 pub fn wrap_with_bank_forks_for_tests(self) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6938 let bank_forks = BankForks::new_rw_arc(self);
6939 let bank = bank_forks.read().unwrap().root_bank();
6940 (bank, bank_forks)
6941 }
6942
6943 pub fn default_for_tests() -> Self {
6944 let accounts_db = AccountsDb::default_for_tests();
6945 let accounts = Accounts::new(Arc::new(accounts_db));
6946 Self::default_with_accounts(accounts)
6947 }
6948
6949 pub fn new_with_bank_forks_for_tests(
6950 genesis_config: &GenesisConfig,
6951 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6952 let bank = Self::new_for_tests(genesis_config);
6953 bank.wrap_with_bank_forks_for_tests()
6954 }
6955
6956 pub fn new_for_tests(genesis_config: &GenesisConfig) -> Self {
6957 Self::new_with_paths_for_tests(genesis_config, None, vec![], None)
6958 }
6959
6960 pub fn new_with_mockup_builtin_for_tests(
6961 genesis_config: &GenesisConfig,
6962 program_id: Pubkey,
6963 builtin: BuiltinFunctionRegisterer,
6964 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
6965 let mut bank = Self::new_for_tests(genesis_config);
6966 bank.add_mockup_builtin(program_id, builtin);
6967 bank.wrap_with_bank_forks_for_tests()
6968 }
6969
6970 pub fn new_with_paths_for_tests(
6971 genesis_config: &GenesisConfig,
6972 test_config: Option<BankTestConfig>,
6973 paths: Vec<PathBuf>,
6974 leader: Option<SlotLeader>,
6975 ) -> Self {
6976 let test_config = test_config.unwrap_or_default();
6977 let mut bank = Self::new_from_genesis(
6978 genesis_config,
6979 Arc::new(RuntimeConfig::default()),
6980 paths,
6981 None,
6982 test_config.accounts_db_config,
6983 None,
6984 leader,
6985 Arc::default(),
6986 None,
6987 None,
6988 );
6989 bank.set_fee_structure(&FeeStructure {
6991 lamports_per_signature: genesis_config.fee_rate_governor.lamports_per_signature,
6992 ..FeeStructure::default()
6993 });
6994 bank
6995 }
6996
6997 pub fn new_for_benches(genesis_config: &GenesisConfig) -> Self {
6998 Self::new_with_paths_for_benches(genesis_config, Vec::new())
6999 }
7000
7001 pub fn new_with_paths_for_benches(genesis_config: &GenesisConfig, paths: Vec<PathBuf>) -> Self {
7004 Self::new_from_genesis(
7005 genesis_config,
7006 Arc::<RuntimeConfig>::default(),
7007 paths,
7008 None,
7009 ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS,
7010 None,
7011 Some(SlotLeader::new_unique()),
7012 Arc::default(),
7013 None,
7014 None,
7015 )
7016 }
7017
7018 pub fn new_from_parent_with_bank_forks(
7019 bank_forks: &RwLock<BankForks>,
7020 parent: Arc<Bank>,
7021 leader: SlotLeader,
7022 slot: Slot,
7023 ) -> Arc<Self> {
7024 let bank = Bank::new_from_parent(parent, leader, slot);
7025 bank_forks
7026 .write()
7027 .unwrap()
7028 .insert(bank)
7029 .clone_without_scheduler()
7030 }
7031
7032 pub fn prepare_batch_for_tests(
7034 &self,
7035 txs: Vec<Transaction>,
7036 ) -> TransactionBatch<'_, '_, RuntimeTransaction<SanitizedTransaction>> {
7037 let sanitized_txs = txs
7038 .into_iter()
7039 .map(RuntimeTransaction::from_transaction_for_tests)
7040 .collect::<Vec<_>>();
7041 TransactionBatch::new(
7042 self.try_lock_accounts(&sanitized_txs),
7043 self,
7044 OwnedOrBorrowed::Owned(sanitized_txs),
7045 )
7046 }
7047
7048 pub fn set_accounts_data_size_initial_for_tests(&mut self, amount: u64) {
7051 self.accounts_data_size_initial = amount;
7052 }
7053
7054 pub fn update_accounts_data_size_delta_off_chain_for_tests(&self, amount: i64) {
7057 self.update_accounts_data_size_delta_off_chain(amount)
7058 }
7059
7060 #[must_use]
7066 pub fn process_transactions<'a>(
7067 &self,
7068 txs: impl Iterator<Item = &'a Transaction>,
7069 ) -> Vec<Result<()>> {
7070 self.try_process_transactions(txs).unwrap()
7071 }
7072
7073 #[must_use]
7079 pub fn process_entry_transactions(&self, txs: Vec<VersionedTransaction>) -> Vec<Result<()>> {
7080 self.try_process_entry_transactions(txs).unwrap()
7081 }
7082
7083 pub fn get_sysvar_cache_for_tests(&self) -> SysvarCache {
7084 self.transaction_processor.get_sysvar_cache_for_tests()
7085 }
7086
7087 pub fn calculate_accounts_lt_hash_for_tests(&self) -> AccountsLtHash {
7088 self.rc
7089 .accounts
7090 .accounts_db
7091 .calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors)
7092 }
7093
7094 pub fn get_transaction_processor(&self) -> &TransactionBatchProcessor<BankForks> {
7095 &self.transaction_processor
7096 }
7097
7098 pub fn set_fee_structure(&mut self, fee_structure: &FeeStructure) {
7099 self.fee_structure = fee_structure.clone();
7100 }
7101
7102 pub fn load_program(
7103 &self,
7104 pubkey: &Pubkey,
7105 effective_epoch: Epoch,
7106 ) -> Option<Arc<ProgramCacheEntry>> {
7107 let environments = self
7108 .transaction_processor
7109 .program_runtime_environment_for_epoch(effective_epoch);
7110 load_program_with_pubkey(
7111 self,
7112 &environments,
7113 pubkey,
7114 self.slot(),
7115 &mut ExecuteTimings::default(), )
7117 .map(|(loaded_program, _last_modification_slot)| loaded_program)
7118 }
7119
7120 pub fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
7121 match self.get_account_with_fixed_root(pubkey) {
7122 Some(mut account) => {
7123 let min_balance = match get_system_account_kind(&account) {
7124 Some(SystemAccountKind::Nonce) => self
7125 .rent_collector
7126 .rent
7127 .minimum_balance(nonce::state::State::size()),
7128 _ => 0,
7129 };
7130
7131 lamports
7132 .checked_add(min_balance)
7133 .filter(|required_balance| *required_balance <= account.lamports())
7134 .ok_or(TransactionError::InsufficientFundsForFee)?;
7135 account
7136 .checked_sub_lamports(lamports)
7137 .map_err(|_| TransactionError::InsufficientFundsForFee)?;
7138 self.store_account(pubkey, &account);
7139
7140 Ok(())
7141 }
7142 None => Err(TransactionError::AccountNotFound),
7143 }
7144 }
7145
7146 pub fn set_hash_overrides(&self, hash_overrides: HashOverrides) {
7147 *self.hash_overrides.lock().unwrap() = hash_overrides;
7148 }
7149
7150 pub(crate) fn get_stake_accounts(&self, minimized_account_set: &DashSet<Pubkey>) {
7152 self.stakes_cache
7153 .stakes()
7154 .stake_delegations()
7155 .iter()
7156 .for_each(|(pubkey, _)| {
7157 minimized_account_set.insert(*pubkey);
7158 });
7159
7160 self.stakes_cache
7161 .stakes()
7162 .staked_nodes()
7163 .par_iter()
7164 .for_each(|(pubkey, _)| {
7165 minimized_account_set.insert(*pubkey);
7166 });
7167 }
7168
7169 pub fn slot_time_reduction_active(&self) -> bool {
7171 self.ns_per_slot != self.slot_params.baseline_params().ns_per_slot()
7172 }
7173}
7174
7175pub(crate) fn rewards_calculation_thread_pool() -> &'static ThreadPool {
7185 static NEW_EPOCH_THREAD_POOL: OnceLock<ThreadPool> = OnceLock::new();
7186 NEW_EPOCH_THREAD_POOL.get_or_init(|| {
7187 rayon::ThreadPoolBuilder::new()
7188 .thread_name(|i| format!("solBnkClcRwds{i:02}"))
7189 .build()
7190 .expect("new epoch boundary rayon threadpool")
7191 })
7192}
7193
7194fn calculate_data_size_delta(old_data_size: usize, new_data_size: usize) -> i64 {
7197 assert!(old_data_size <= i64::MAX as usize);
7198 assert!(new_data_size <= i64::MAX as usize);
7199 let old_data_size = old_data_size as i64;
7200 let new_data_size = new_data_size as i64;
7201
7202 new_data_size.saturating_sub(old_data_size)
7203}
7204
7205impl Drop for Bank {
7206 fn drop(&mut self) {
7207 self.clear_accounts_lt_hash_async_progress_is_at_end();
7208 if let Some(drop_callback) = self.drop_callback.read().unwrap().0.as_ref() {
7209 drop_callback.callback(self);
7210 } else {
7211 self.rc
7213 .accounts
7214 .accounts_db
7215 .purge_slot(self.slot(), self.bank_id(), false);
7216 }
7217 }
7218}
7219
7220pub mod test_utils {
7222 use {
7223 super::Bank,
7224 crate::installed_scheduler_pool::BankWithScheduler,
7225 solana_account::{ReadableAccount, WritableAccount, state_traits::StateMutWincode as _},
7226 solana_instruction::error::LamportsError,
7227 solana_pubkey::Pubkey,
7228 solana_sha256_hasher::hashv,
7229 solana_vote_interface::state::VoteStateV4,
7230 solana_vote_program::vote_state::{BlockTimestamp, VoteStateVersions},
7231 std::sync::Arc,
7232 };
7233 pub fn goto_end_of_slot(bank: Arc<Bank>) {
7234 goto_end_of_slot_with_scheduler(&BankWithScheduler::new_without_scheduler(bank))
7235 }
7236
7237 pub fn goto_end_of_slot_with_scheduler(bank: &BankWithScheduler) {
7238 let mut tick_hash = bank.last_blockhash();
7239 loop {
7240 tick_hash = hashv(&[tick_hash.as_ref(), &[42]]);
7241 bank.register_tick(&tick_hash);
7242 if tick_hash == bank.last_blockhash() {
7243 bank.freeze();
7244 return;
7245 }
7246 }
7247 }
7248
7249 pub fn update_vote_account_timestamp(
7250 timestamp: BlockTimestamp,
7251 bank: &Bank,
7252 vote_pubkey: &Pubkey,
7253 ) {
7254 let mut vote_account = bank.get_account(vote_pubkey).unwrap_or_default();
7255 let mut vote_state = VoteStateV4::deserialize(vote_account.data(), vote_pubkey)
7256 .ok()
7257 .unwrap_or_default();
7258 vote_state.last_timestamp = timestamp;
7259 let versioned = VoteStateVersions::new_v4(vote_state);
7260 vote_account.set_state(&versioned).unwrap();
7261 bank.store_account(vote_pubkey, &vote_account);
7262 }
7263
7264 pub fn deposit(
7265 bank: &Bank,
7266 pubkey: &Pubkey,
7267 lamports: u64,
7268 ) -> std::result::Result<u64, LamportsError> {
7269 let mut account = bank
7272 .get_account_with_fixed_root_no_cache(pubkey)
7273 .unwrap_or_default();
7274 account.checked_add_lamports(lamports)?;
7275 bank.store_account(pubkey, &account);
7276 Ok(account.lamports())
7277 }
7278}