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