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