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