1pub use {
37 crate::slot_params::DEFAULT_MAX_ENTRY_BYTES_PER_SLOT,
38 partitioned_epoch_rewards::KeyedRewardsAndNumPartitions, solana_leader_schedule::SlotLeader,
39 solana_reward_info::RewardType,
40};
41use {
42 crate::{
43 account_saver::collect_accounts_to_store,
44 alpenglow_epoch_type::AlpenglowEpochType,
45 bank::{
46 entry_bytes_budget::EntryBytesBudget,
47 metrics::*,
48 partitioned_epoch_rewards::{CachedVoteAccounts, EpochRewardStatus},
49 },
50 bank_forks::BankForks,
51 block_component_processor::{
52 BlockComponentProcessor,
53 vote_reward::epoch_inflation_account_state::EpochInflationAccountState,
54 },
55 epoch_stakes::{
56 BLSPubkeyToRankMap, DeserializableVersionedEpochStakes, NodeVoteAccounts,
57 VersionedEpochStakes,
58 },
59 inflation_rewards::points::InflationPointCalculationEvent,
60 installed_scheduler_pool::{BankWithScheduler, InstalledSchedulerRwLock},
61 leader_schedule_utils::leader_schedule_from_vote_accounts,
62 rent_collector::RentCollector,
63 reward_info::RewardInfo,
64 runtime_config::RuntimeConfig,
65 slot_params::{SlotParams, SlotParamsArchive},
66 stake_account::StakeAccount,
67 stake_history::StakeHistory as CowStakeHistory,
68 stake_weighted_timestamp::{
69 MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST, MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
70 MaxAllowableDrift, calculate_stake_weighted_timestamp,
71 },
72 stakes::{
73 DelegatedStakes, DeserializableDelegationStakes, SerdeStakesToStakeFormat, Stakes,
74 StakesCache,
75 },
76 status_cache::{SlotDelta, StatusCache},
77 sysvar_account::{create_account, create_account_with_bincode, from_account},
78 transaction_batch::{OwnedOrBorrowed, TransactionBatch},
79 },
80 accounts_lt_hash::AccountsLtHashAsyncProgress,
81 agave_bls_cert_verify::cert_verify::{self, Error as CertVerifyError},
82 agave_feature_set::{self as feature_set, FeatureSet},
83 agave_precompiles::{get_precompile, get_precompiles, is_precompile},
84 agave_reserved_account_keys::ReservedAccountKeys,
85 agave_snapshots::snapshot_hash::SnapshotHash,
86 agave_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 filtered_distribution_vote_accounts: VoteAccounts,
1257 rewards_calculation: Arc<PartitionedRewardsCalculation>,
1258 calculate_activated_stake_time_us: u64,
1259 update_rewards_with_thread_pool_time_us: u64,
1260}
1261
1262impl Bank {
1263 fn default_with_accounts(accounts: Accounts) -> Self {
1264 let partitioned_rewards_stake_account_stores_per_block = accounts
1265 .accounts_db
1266 .partitioned_epoch_rewards_config
1267 .stake_account_stores_per_block;
1268 let mut bank = Self {
1269 rc: BankRc::new(accounts),
1270 status_cache: Arc::<RwLock<BankStatusCache>>::default(),
1271 store_transaction_signatures_in_status_cache: !RuntimeConfig::default()
1272 .skip_transaction_signatures_in_status_cache,
1273 blockhash_queue: RwLock::<BlockhashQueue>::default(),
1274 max_processing_age: MAX_PROCESSING_AGE,
1275 partitioned_rewards_stake_account_stores_per_block,
1276 ancestors: Ancestors::default(),
1277 hash: RwLock::<Hash>::default(),
1278 parent_hash: Hash::default(),
1279 parent_slot: Slot::default(),
1280 hard_forks: Arc::<RwLock<HardForks>>::default(),
1281 transaction_count: AtomicU64::default(),
1282 non_vote_transaction_count_since_restart: AtomicU64::default(),
1283 transaction_error_count: AtomicU64::default(),
1284 transaction_entries_count: AtomicU64::default(),
1285 transactions_per_entry_max: AtomicU64::default(),
1286 entry_bytes_consumed: EntryBytesBudget::new(DEFAULT_MAX_ENTRY_BYTES_PER_SLOT),
1287 tick_height: AtomicU64::default(),
1288 signature_count: AtomicU64::default(),
1289 capitalization: AtomicU64::default(),
1290 max_tick_height: u64::default(),
1291 hashes_per_tick: RwLock::default(),
1292 ticks_per_slot: u64::default(),
1293 ns_per_slot: u128::default(),
1294 genesis_creation_time: UnixTimestamp::default(),
1295 slots_per_year: f64::default(),
1296 slot_params: SlotParamsArchive::default(),
1297 slot: Slot::default(),
1298 bank_id: BankId::default(),
1299 epoch: Epoch::default(),
1300 block_height: u64::default(),
1301 leader: SlotLeader::default(),
1302 fee_rate_governor: FeeRateGovernor::default(),
1303 rent_collector: RentCollector::default(),
1304 epoch_schedule: EpochSchedule::default(),
1305 inflation: Arc::<RwLock<Inflation>>::default(),
1306 stakes_cache: StakesCache::default(),
1307 epoch_stakes: HashMap::<Epoch, VersionedEpochStakes>::default(),
1308 is_delta: AtomicBool::default(),
1309 rewards: RwLock::<Vec<(Pubkey, RewardInfo)>>::default(),
1310 cluster_type: Option::<ClusterType>::default(),
1311 transaction_debug_keys: Option::<Arc<HashSet<Pubkey>>>::default(),
1312 transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
1313 ),
1314 transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
1315 feature_set: Arc::<FeatureSet>::default(),
1316 reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
1317 drop_callback: RwLock::new(OptionalDropCallback(None)),
1318 freeze_started: AtomicBool::default(),
1319 vote_only_bank: false,
1320 should_replay_from_blockstore: true,
1321 cost_tracker: RwLock::<CostTracker>::default(),
1322 accounts_data_size_initial: 0,
1323 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1324 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1325 epoch_reward_status: EpochRewardStatus::default(),
1326 transaction_processor: TransactionBatchProcessor::default(),
1327 collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1328 compute_budget: None,
1329 transaction_account_lock_limit: None,
1330 fee_structure: FeeStructure::default(),
1331 #[cfg(feature = "dev-context-only-utils")]
1332 hash_overrides: Arc::new(Mutex::new(HashOverrides::default())),
1333 accounts_lt_hash: Mutex::new(AccountsLtHash(LtHash::identity())),
1334 accounts_lt_hash_async_progress: Arc::new(AccountsLtHashAsyncProgress::new()),
1335 block_id: RwLock::new(None),
1336 expected_bank_hash: RwLock::new(None),
1337 bank_hash_stats: AtomicBankHashStats::default(),
1338 epoch_rewards_calculation_cache: Arc::new(Mutex::new(HashMap::default())),
1339 block_component_processor: RwLock::new(BlockComponentProcessor::default()),
1340 is_alpenglow: AtomicBool::new(false),
1341 transaction_execution_gate: CachePadded::new(TransactionExecutionGate::default()),
1342 };
1343
1344 bank.transaction_processor =
1345 TransactionBatchProcessor::new_uninitialized(bank.slot, bank.epoch);
1346
1347 bank.accounts_data_size_initial = bank.calculate_accounts_data_size().unwrap();
1348
1349 bank
1350 }
1351
1352 #[expect(clippy::too_many_arguments)]
1353 pub fn new_from_genesis(
1354 genesis_config: &GenesisConfig,
1355 runtime_config: Arc<RuntimeConfig>,
1356 paths: Vec<PathBuf>,
1357 debug_keys: Option<Arc<HashSet<Pubkey>>>,
1358 accounts_db_config: AccountsDbConfig,
1359 accounts_update_notifier: Option<AccountsUpdateNotifier>,
1360 #[cfg_attr(not(feature = "dev-context-only-utils"), expect(unused))]
1361 leader_for_tests: Option<SlotLeader>,
1362 exit: Arc<AtomicBool>,
1363 #[cfg_attr(not(feature = "dev-context-only-utils"), expect(unused))] genesis_hash: Option<
1364 Hash,
1365 >,
1366 #[cfg_attr(not(feature = "dev-context-only-utils"), expect(unused))] feature_set: Option<
1367 FeatureSet,
1368 >,
1369 ) -> Self {
1370 let _rewards_calculation_thread_pool = rewards_calculation_thread_pool();
1373 let accounts_db =
1374 AccountsDb::new_with_config(paths, accounts_db_config, accounts_update_notifier, exit);
1375 let accounts = Accounts::new(Arc::new(accounts_db));
1376 let mut bank = Self::default_with_accounts(accounts);
1377 bank.ancestors = Ancestors::from(vec![bank.slot()]);
1378 bank.compute_budget = runtime_config.compute_budget;
1379 bank.store_transaction_signatures_in_status_cache =
1380 !runtime_config.skip_transaction_signatures_in_status_cache;
1381 if let Some(compute_budget) = &bank.compute_budget {
1382 bank.transaction_processor
1383 .set_execution_cost(compute_budget.to_cost());
1384 }
1385 bank.transaction_account_lock_limit = runtime_config.transaction_account_lock_limit;
1386 bank.transaction_debug_keys = debug_keys;
1387 bank.cluster_type = Some(genesis_config.cluster_type);
1388
1389 #[cfg(feature = "dev-context-only-utils")]
1390 {
1391 bank.feature_set = Arc::new(feature_set.unwrap_or_default());
1392 }
1393
1394 #[cfg(not(feature = "dev-context-only-utils"))]
1395 bank.process_genesis_config(genesis_config);
1396 #[cfg(feature = "dev-context-only-utils")]
1397 bank.process_genesis_config(genesis_config, leader_for_tests, genesis_hash);
1398
1399 bank.compute_and_apply_genesis_features();
1400
1401 {
1404 let stakes = bank.get_top_epoch_stakes();
1405 let stakes = SerdeStakesToStakeFormat::from(stakes);
1406 for epoch in 0..=bank.get_leader_schedule_epoch(bank.slot) {
1407 bank.epoch_stakes
1408 .insert(epoch, VersionedEpochStakes::new(stakes.clone(), epoch));
1409 }
1410 bank.update_stake_history(None);
1411 }
1412 bank.update_clock(None);
1413 bank.update_rent();
1414 bank.update_epoch_schedule();
1415 bank.update_recent_blockhashes();
1416 bank.update_last_restart_slot();
1417 bank.transaction_processor
1418 .fill_missing_sysvar_cache_entries(&bank);
1419 if bank.get_alpenglow_genesis_certificate().is_some() {
1420 bank.set_is_alpenglow();
1421 }
1422 bank
1423 }
1424
1425 pub fn new_from_parent(parent: Arc<Bank>, leader: SlotLeader, slot: Slot) -> Self {
1427 Self::_new_from_parent(
1428 parent,
1429 leader,
1430 slot,
1431 null_tracer(),
1432 NewBankOptions::default(),
1433 )
1434 }
1435
1436 pub fn new_from_parent_with_options(
1437 parent: Arc<Bank>,
1438 leader: SlotLeader,
1439 slot: Slot,
1440 new_bank_options: NewBankOptions,
1441 ) -> Self {
1442 Self::_new_from_parent(parent, leader, slot, null_tracer(), new_bank_options)
1443 }
1444
1445 pub fn new_from_parent_with_tracer(
1446 parent: Arc<Bank>,
1447 leader: SlotLeader,
1448 slot: Slot,
1449 reward_calc_tracer: impl RewardCalcTracer,
1450 ) -> Self {
1451 Self::_new_from_parent(
1452 parent,
1453 leader,
1454 slot,
1455 Some(reward_calc_tracer),
1456 NewBankOptions::default(),
1457 )
1458 }
1459
1460 fn get_rent_collector_from(rent_collector: &RentCollector, epoch: Epoch) -> RentCollector {
1461 rent_collector.clone_with_epoch(epoch)
1462 }
1463
1464 fn _new_from_parent(
1465 parent: Arc<Bank>,
1466 leader: SlotLeader,
1467 slot: Slot,
1468 reward_calc_tracer: Option<impl RewardCalcTracer>,
1469 new_bank_options: NewBankOptions,
1470 ) -> Self {
1471 let mut time = Measure::start("bank::new_from_parent");
1472 let NewBankOptions { vote_only_bank } = new_bank_options;
1473
1474 parent.freeze();
1475 assert_ne!(slot, parent.slot());
1476
1477 let epoch_schedule = parent.epoch_schedule().clone();
1478 let epoch = epoch_schedule.get_epoch(slot);
1479
1480 let (rc, bank_rc_creation_time_us) = measure_us!({
1481 let accounts_db = Arc::clone(&parent.rc.accounts.accounts_db);
1482 BankRc {
1483 accounts: Arc::new(Accounts::new(accounts_db)),
1484 parent: RwLock::new(Some(Arc::clone(&parent))),
1485 bank_id_generator: Arc::clone(&parent.rc.bank_id_generator),
1486 }
1487 });
1488
1489 let (status_cache, status_cache_time_us) = measure_us!(Arc::clone(&parent.status_cache));
1490
1491 let (fee_rate_governor, fee_components_time_us) = measure_us!(
1492 FeeRateGovernor::new_derived(&parent.fee_rate_governor, parent.signature_count())
1493 );
1494
1495 let bank_id = rc.bank_id_generator.fetch_add(1, Relaxed) + 1;
1496 let (blockhash_queue, blockhash_queue_time_us) =
1497 measure_us!(RwLock::new(parent.blockhash_queue.read().unwrap().clone()));
1498
1499 let (stakes_cache, stakes_cache_time_us) =
1500 measure_us!(StakesCache::new(parent.stakes_cache.stakes().clone()));
1501
1502 let (epoch_stakes, epoch_stakes_time_us) = measure_us!(parent.epoch_stakes.clone());
1503
1504 let (transaction_processor, builtin_program_ids_time_us) = measure_us!(
1505 TransactionBatchProcessor::new_from(&parent.transaction_processor, slot, epoch)
1506 );
1507
1508 let (transaction_debug_keys, transaction_debug_keys_time_us) =
1509 measure_us!(parent.transaction_debug_keys.clone());
1510
1511 let (transaction_log_collector_config, transaction_log_collector_config_time_us) =
1512 measure_us!(parent.transaction_log_collector_config.clone());
1513
1514 let (feature_set, feature_set_time_us) = measure_us!(parent.feature_set.clone());
1515
1516 let accounts_data_size_initial = parent.load_accounts_data_size();
1517 let mut new = Self {
1518 rc,
1519 status_cache,
1520 store_transaction_signatures_in_status_cache: parent
1521 .store_transaction_signatures_in_status_cache,
1522 slot,
1523 bank_id,
1524 epoch,
1525 blockhash_queue,
1526 max_processing_age: parent.max_processing_age,
1527 partitioned_rewards_stake_account_stores_per_block: parent
1528 .partitioned_rewards_stake_account_stores_per_block,
1529 hashes_per_tick: RwLock::new(parent.hashes_per_tick()),
1531 ticks_per_slot: parent.ticks_per_slot,
1532 ns_per_slot: parent.ns_per_slot,
1533 genesis_creation_time: parent.genesis_creation_time,
1534 slots_per_year: parent.slots_per_year,
1535 slot_params: parent.slot_params.clone(),
1536 epoch_schedule,
1537 rent_collector: Self::get_rent_collector_from(&parent.rent_collector, epoch),
1538 max_tick_height: slot
1539 .checked_add(1)
1540 .expect("max tick height addition overflowed")
1541 .checked_mul(parent.ticks_per_slot)
1542 .expect("max tick height multiplication overflowed"),
1543 block_height: parent
1544 .block_height
1545 .checked_add(1)
1546 .expect("block height addition overflowed"),
1547 fee_rate_governor,
1548 capitalization: AtomicU64::new(parent.capitalization()),
1549 vote_only_bank,
1550 should_replay_from_blockstore: true,
1551 inflation: parent.inflation.clone(),
1552 transaction_count: AtomicU64::new(parent.transaction_count()),
1553 non_vote_transaction_count_since_restart: AtomicU64::new(
1554 parent.non_vote_transaction_count_since_restart(),
1555 ),
1556 transaction_error_count: AtomicU64::new(0),
1557 transaction_entries_count: AtomicU64::new(0),
1558 transactions_per_entry_max: AtomicU64::new(0),
1559 entry_bytes_consumed: EntryBytesBudget::new(parent.entry_bytes_budget().slot_limit()),
1560 stakes_cache,
1562 epoch_stakes,
1563 parent_hash: parent.hash(),
1564 parent_slot: parent.slot(),
1565 leader,
1566 ancestors: Ancestors::default(),
1567 hash: RwLock::new(Hash::default()),
1568 is_delta: AtomicBool::new(false),
1569 tick_height: AtomicU64::new(parent.tick_height.load(Relaxed)),
1570 signature_count: AtomicU64::new(0),
1571 hard_forks: parent.hard_forks.clone(),
1572 rewards: RwLock::new(vec![]),
1573 cluster_type: parent.cluster_type,
1574 transaction_debug_keys,
1575 transaction_log_collector_config,
1576 transaction_log_collector: Arc::new(RwLock::new(TransactionLogCollector::default())),
1577 feature_set: Arc::clone(&feature_set),
1578 reserved_account_keys: parent.reserved_account_keys.clone(),
1579 drop_callback: RwLock::new(OptionalDropCallback(
1580 parent
1581 .drop_callback
1582 .read()
1583 .unwrap()
1584 .0
1585 .as_ref()
1586 .map(|drop_callback| drop_callback.clone_box()),
1587 )),
1588 freeze_started: AtomicBool::new(false),
1589 cost_tracker: RwLock::new(parent.read_cost_tracker().unwrap().new_from_parent_limits()),
1590 accounts_data_size_initial,
1591 accounts_data_size_delta_on_chain: AtomicI64::new(0),
1592 accounts_data_size_delta_off_chain: AtomicI64::new(0),
1593 epoch_reward_status: parent.epoch_reward_status.clone(),
1594 transaction_processor,
1595 collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
1596 compute_budget: parent.compute_budget,
1597 transaction_account_lock_limit: parent.transaction_account_lock_limit,
1598 fee_structure: parent.fee_structure.clone(),
1599 #[cfg(feature = "dev-context-only-utils")]
1600 hash_overrides: parent.hash_overrides.clone(),
1601 accounts_lt_hash: Mutex::new(parent.accounts_lt_hash.lock().unwrap().clone()),
1602 accounts_lt_hash_async_progress: Arc::new(AccountsLtHashAsyncProgress::new()),
1603 block_id: RwLock::new(None),
1604 expected_bank_hash: RwLock::new(None),
1605 bank_hash_stats: AtomicBankHashStats::default(),
1606 epoch_rewards_calculation_cache: parent.epoch_rewards_calculation_cache.clone(),
1607 block_component_processor: RwLock::new(BlockComponentProcessor::default()),
1608 is_alpenglow: AtomicBool::new(parent.is_alpenglow()),
1609 transaction_execution_gate: CachePadded::new(TransactionExecutionGate::default()),
1610 };
1611
1612 let (_, ancestors_time_us) = measure_us!({
1613 let mut ancestors = Vec::with_capacity(parent.ancestors.len() + 1);
1614 ancestors.push(new.slot());
1615 ancestors.extend(new.parents_iter().map(|parent| parent.slot()));
1616 new.ancestors = Ancestors::from(ancestors);
1617 });
1618
1619 let prepare_timings = new.prepare_for_block_execution(
1620 parent.epoch(),
1621 parent.slot(),
1622 parent.capitalization(),
1623 parent.block_height(),
1624 reward_calc_tracer,
1625 );
1626
1627 time.stop();
1628 report_new_bank_metrics(
1629 slot,
1630 parent.slot(),
1631 new.block_height,
1632 NewBankTimings {
1633 bank_rc_creation_time_us,
1634 total_elapsed_time_us: time.as_us(),
1635 status_cache_time_us,
1636 fee_components_time_us,
1637 blockhash_queue_time_us,
1638 stakes_cache_time_us,
1639 epoch_stakes_time_us,
1640 builtin_program_ids_time_us,
1641 executor_cache_time_us: 0,
1642 transaction_debug_keys_time_us,
1643 transaction_log_collector_config_time_us,
1644 feature_set_time_us,
1645 ancestors_time_us,
1646 update_epoch_time_us: prepare_timings.update_epoch_time_us,
1647 distribute_rewards_time_us: prepare_timings.distribute_rewards_time_us,
1648 cache_preparation_time_us: prepare_timings.cache_preparation_time_us,
1649 update_sysvars_time_us: prepare_timings.update_sysvars_time_us,
1650 fill_sysvar_cache_time_us: prepare_timings.fill_sysvar_cache_time_us,
1651 },
1652 );
1653
1654 report_loaded_programs_stats(
1655 &parent
1656 .transaction_processor
1657 .global_program_cache
1658 .read()
1659 .unwrap(),
1660 parent.slot(),
1661 );
1662
1663 new.transaction_processor
1664 .global_program_cache
1665 .write()
1666 .unwrap()
1667 .stats
1668 .reset();
1669
1670 new
1671 }
1672
1673 pub fn set_fork_graph_in_program_cache(&self, fork_graph: Weak<RwLock<BankForks>>) {
1674 self.transaction_processor
1675 .global_program_cache
1676 .write()
1677 .unwrap()
1678 .set_fork_graph(fork_graph);
1679 }
1680
1681 fn prepare_program_cache_for_upcoming_feature_set(&self) {
1682 let (_epoch, slot_index) = self.epoch_schedule.get_epoch_and_slot_index(self.slot);
1683 let slots_in_epoch = self.epoch_schedule.get_slots_in_epoch(self.epoch);
1684 let (upcoming_feature_set, _newly_activated) = self.compute_active_feature_set(true);
1685
1686 let slots_in_recompilation_phase =
1688 (solana_program_runtime::loaded_programs::MAX_LOADED_ENTRY_COUNT as u64)
1689 .min(slots_in_epoch)
1690 .checked_div(2)
1691 .unwrap();
1692
1693 let mut epoch_boundary_preparation = self
1694 .transaction_processor
1695 .epoch_boundary_preparation
1696 .write()
1697 .unwrap();
1698
1699 if let Some(upcoming_environment) = epoch_boundary_preparation.upcoming_environment.as_ref()
1700 {
1701 let upcoming_environment = upcoming_environment.clone();
1702 if let Some((key, program_to_recompile)) =
1703 epoch_boundary_preparation.programs_to_recompile.pop()
1704 {
1705 drop(epoch_boundary_preparation);
1706 self.transaction_processor
1707 .prepare_one_program_for_upcoming_feature_set(
1708 self,
1709 &upcoming_environment,
1710 &key,
1711 &program_to_recompile.stats,
1712 );
1713 }
1714 } else if slot_index.saturating_add(slots_in_recompilation_phase) >= slots_in_epoch {
1715 let new_environment = self.create_program_runtime_environment(&upcoming_feature_set);
1718 let mut upcoming_environment = self
1719 .transaction_processor
1720 .program_runtime_environment
1721 .clone();
1722 let changed_program_runtime_environment = *upcoming_environment != *new_environment;
1724 if changed_program_runtime_environment {
1725 upcoming_environment = new_environment;
1726 let program_cache_guard = self
1727 .transaction_processor
1728 .global_program_cache
1729 .read()
1730 .unwrap();
1731 epoch_boundary_preparation.programs_to_recompile =
1732 program_cache_guard.get_flattened_entries();
1733 epoch_boundary_preparation
1734 .programs_to_recompile
1735 .sort_by_cached_key(|(_id, program)| program.retention_score());
1736 } else {
1737 epoch_boundary_preparation.programs_to_recompile.clear();
1738 }
1739 epoch_boundary_preparation.upcoming_epoch = self.epoch.saturating_add(1);
1740 epoch_boundary_preparation.upcoming_environment = Some(upcoming_environment);
1741 }
1742 }
1743
1744 pub fn prune_program_cache(&self, bank_forks: &BankForks) {
1745 let upcoming_environment = self
1746 .transaction_processor
1747 .epoch_boundary_preparation
1748 .write()
1749 .unwrap()
1750 .reroot(self.epoch());
1751 self.transaction_processor
1752 .global_program_cache
1753 .write()
1754 .unwrap()
1755 .prune(
1756 self.slot(),
1757 upcoming_environment.map(|_| {
1758 ProgramRuntimeEnvironment::clone(
1759 &self.transaction_processor.program_runtime_environment,
1760 )
1761 }),
1762 bank_forks,
1763 );
1764 }
1765
1766 pub fn prune_program_cache_by_deployment_slot(&self, deployment_slot: Slot) {
1767 self.transaction_processor
1768 .global_program_cache
1769 .write()
1770 .unwrap()
1771 .prune_by_deployment_slot(deployment_slot);
1772 }
1773
1774 pub fn new_warmup_cooldown_rate_epoch(&self) -> Option<Epoch> {
1776 self.feature_set
1777 .new_warmup_cooldown_rate_epoch(&self.epoch_schedule)
1778 }
1779
1780 fn use_fixed_point_stake_math(&self) -> bool {
1781 self.feature_set
1782 .snapshot()
1783 .upgrade_bpf_stake_program_to_v5_1
1784 }
1785
1786 fn get_cached_vote_accounts<'a>(
1790 &'a self,
1791 rewarded_epoch: Epoch,
1792 distribution_epoch_vote_accounts: &'a VoteAccounts,
1793 ) -> CachedVoteAccounts<'a> {
1794 let snapshot_epoch_vote_accounts = self
1798 .epoch_stakes(rewarded_epoch)
1799 .map(|epoch_stakes| epoch_stakes.stakes().vote_accounts());
1800
1801 let rewarded_epoch_vote_accounts = self
1803 .epoch_stakes(self.epoch())
1804 .map(|epoch_stakes| epoch_stakes.stakes().vote_accounts());
1805
1806 CachedVoteAccounts {
1807 snapshot_epoch_vote_accounts,
1808 rewarded_epoch_vote_accounts,
1809 distribution_epoch_vote_accounts,
1810 }
1811 }
1812
1813 fn compute_new_epoch_caches_and_rewards(
1816 &self,
1817 thread_pool: &ThreadPool,
1818 rewarded_epoch: Epoch,
1819 reward_calc_tracer: Option<impl RewardCalcTracer>,
1820 rewards_metrics: &mut RewardsMetrics,
1821 ) -> NewEpochBundle {
1822 let stakes = self.stakes_cache.stakes();
1826 let stake_delegations = stakes.stake_delegations_vec();
1827 let (
1828 (
1829 stake_history,
1830 unfiltered_distribution_vote_accounts,
1831 delegated_stakes,
1832 reward_epoch_delegated_stakes,
1833 ),
1834 calculate_activated_stake_time_us,
1835 ) = measure_us!(stakes.calculate_activated_stake(
1836 self.epoch(),
1837 thread_pool,
1838 self.new_warmup_cooldown_rate_epoch(),
1839 &stake_delegations,
1840 self.use_fixed_point_stake_math(),
1841 ));
1842 debug_assert_eq!(reward_epoch_delegated_stakes.epoch, rewarded_epoch);
1843
1844 let filtered_distribution_vote_accounts = unfiltered_distribution_vote_accounts
1847 .clone_and_filter_for_vat(
1848 MAX_ALPENGLOW_VOTE_ACCOUNTS,
1849 self.minimum_vote_account_balance_for_vat(),
1850 );
1851 if AlpenglowEpochType::is_alpenglow_or_migration_epoch(self, rewarded_epoch) {
1852 reward_epoch_delegated_stakes.set(self, &filtered_distribution_vote_accounts);
1853 }
1854 let cached_vote_accounts =
1855 self.get_cached_vote_accounts(rewarded_epoch, &filtered_distribution_vote_accounts);
1856 let (rewards_calculation, update_rewards_with_thread_pool_time_us) =
1857 measure_us!(self.calculate_rewards(
1858 &stake_history,
1859 stake_delegations,
1860 cached_vote_accounts,
1861 rewarded_epoch,
1862 reward_epoch_delegated_stakes,
1863 reward_calc_tracer,
1864 thread_pool,
1865 rewards_metrics,
1866 ));
1867 NewEpochBundle {
1868 stake_history,
1869 unfiltered_distribution_vote_accounts,
1870 delegated_stakes,
1871 filtered_distribution_vote_accounts,
1872 rewards_calculation,
1873 calculate_activated_stake_time_us,
1874 update_rewards_with_thread_pool_time_us,
1875 }
1876 }
1877
1878 fn process_new_epoch(
1880 &mut self,
1881 parent_epoch: Epoch,
1882 parent_slot: Slot,
1883 parent_capitalization: u64,
1884 parent_height: u64,
1885 reward_calc_tracer: Option<impl RewardCalcTracer>,
1886 ) {
1887 let epoch = self.epoch();
1888 let slot = self.slot();
1889 let thread_pool = rewards_calculation_thread_pool();
1890
1891 let (_, apply_feature_activations_time_us) = measure_us!(
1892 thread_pool.install(|| { self.compute_and_apply_new_feature_activations() })
1893 );
1894
1895 let mut rewards_metrics = RewardsMetrics::default();
1896 let NewEpochBundle {
1897 stake_history,
1898 unfiltered_distribution_vote_accounts,
1899 delegated_stakes,
1900 filtered_distribution_vote_accounts,
1901 rewards_calculation,
1902 calculate_activated_stake_time_us,
1903 update_rewards_with_thread_pool_time_us,
1904 } = self.compute_new_epoch_caches_and_rewards(
1905 thread_pool,
1906 parent_epoch,
1907 reward_calc_tracer,
1908 &mut rewards_metrics,
1909 );
1910
1911 self.stakes_cache.activate_epoch(
1912 epoch,
1913 stake_history,
1914 unfiltered_distribution_vote_accounts,
1915 delegated_stakes,
1916 );
1917
1918 let leader_schedule_epoch = self.epoch_schedule.get_leader_schedule_epoch(slot);
1920 let (_, update_epoch_stakes_time_us) = measure_us!(self.update_epoch_stakes(
1921 leader_schedule_epoch,
1922 Some(filtered_distribution_vote_accounts),
1923 ));
1924
1925 let (epoch_rewards, begin_partitioned_rewards_time_us) =
1928 measure_us!(self.begin_partitioned_rewards(
1929 parent_epoch,
1930 parent_slot,
1931 parent_height,
1932 &rewards_calculation,
1933 &mut rewards_metrics,
1934 thread_pool,
1935 ));
1936
1937 if self.feature_set.snapshot().alpenglow {
1940 let epoch_start_capitalization = parent_capitalization;
1941 EpochInflationAccountState::new_epoch_update_account(
1942 self,
1943 epoch_start_capitalization,
1944 epoch_rewards,
1945 );
1946 }
1947
1948 report_new_epoch_metrics(
1949 epoch,
1950 slot,
1951 parent_slot,
1952 NewEpochTimings {
1953 apply_feature_activations_time_us,
1954 calculate_activated_stake_time_us,
1955 update_epoch_stakes_time_us,
1956 update_rewards_with_thread_pool_time_us,
1957 begin_partitioned_rewards_time_us,
1958 },
1959 rewards_metrics,
1960 );
1961
1962 let program_runtime_environment =
1963 self.create_program_runtime_environment(&self.feature_set);
1964 self.transaction_processor
1965 .set_program_runtime_environment(program_runtime_environment);
1966 }
1967
1968 pub fn proper_ancestors_set(&self) -> HashSet<Slot> {
1969 HashSet::from_iter(self.proper_ancestors())
1970 }
1971
1972 pub(crate) fn proper_ancestors(&self) -> impl Iterator<Item = Slot> + '_ {
1974 self.ancestors
1975 .keys()
1976 .into_iter()
1977 .filter(move |slot| *slot != self.slot)
1978 }
1979
1980 pub fn set_callback(&self, callback: Option<Box<dyn DropCallback + Send + Sync>>) {
1981 *self.drop_callback.write().unwrap() = OptionalDropCallback(callback);
1982 }
1983
1984 pub fn vote_only_bank(&self) -> bool {
1985 self.vote_only_bank
1986 }
1987
1988 pub fn should_replay_from_blockstore(&self) -> bool {
1989 self.should_replay_from_blockstore
1990 }
1991
1992 pub fn mark_leader_bank(mut self) -> Self {
1994 self.should_replay_from_blockstore = false;
1995 self
1996 }
1997
1998 pub fn warp_from_parent(parent: Arc<Bank>, leader: SlotLeader, slot: Slot) -> Self {
2004 parent.freeze();
2005 let parent_timestamp = parent.clock().unix_timestamp;
2006 let mut new = Bank::new_from_parent(parent, leader, slot);
2007 new.update_epoch_stakes(new.epoch_schedule().get_epoch(slot), None);
2008 new.tick_height.store(new.max_tick_height(), Relaxed);
2009
2010 let mut clock = new.clock();
2011 clock.epoch_start_timestamp = parent_timestamp;
2012 clock.unix_timestamp = parent_timestamp;
2013 new.update_sysvar_account(&sysvar::clock::id(), |account| {
2014 create_account(
2015 &clock,
2016 new.inherit_specially_retained_account_fields(account),
2017 )
2018 });
2019 new.transaction_processor
2020 .fill_missing_sysvar_cache_entries(&new);
2021 new.freeze();
2022 new
2023 }
2024
2025 fn load_rent_from_account_for_snapshot_load(
2026 accounts: &Accounts,
2027 ancestors: &Ancestors,
2028 ) -> Rent {
2029 let rent_sysvar = accounts
2032 .load_with_fixed_root_do_not_populate_read_cache(ancestors, &sysvar::rent::id())
2033 .expect("snapshot must contain rent sysvar account")
2034 .0;
2035 from_account::<sysvar::rent::Rent>(&rent_sysvar)
2036 .expect("snapshot must contain well-formed rent sysvar account")
2037 }
2038
2039 fn prepare_for_block_execution(
2044 &mut self,
2045 parent_epoch: Epoch,
2046 parent_slot: Slot,
2047 parent_capitalization: u64,
2048 parent_block_height: u64,
2049 reward_calc_tracer: Option<impl RewardCalcTracer>,
2050 ) -> PrepareBlockExecutionStats {
2051 let slot = self.slot;
2052
2053 let (_, update_epoch_time_us) = measure_us!({
2055 if parent_epoch < self.epoch() {
2056 self.process_new_epoch(
2057 parent_epoch,
2058 parent_slot,
2059 parent_capitalization,
2060 parent_block_height,
2061 reward_calc_tracer,
2062 );
2063 } else {
2064 let leader_schedule_epoch = self.epoch_schedule().get_leader_schedule_epoch(slot);
2066 self.update_epoch_stakes(leader_schedule_epoch, None);
2067 }
2068 });
2069
2070 let (_, distribute_rewards_time_us) =
2071 measure_us!(self.distribute_partitioned_epoch_rewards());
2072
2073 let (_, cache_preparation_time_us) =
2074 measure_us!(self.prepare_program_cache_for_upcoming_feature_set());
2075
2076 let (_, update_sysvars_time_us) = measure_us!({
2078 self.update_slot_hashes();
2079 self.update_stake_history(Some(parent_epoch));
2080
2081 if self.is_alpenglow() {
2082 self.update_clock_slot_for_alpenglow();
2085 } else {
2086 self.update_clock(Some(parent_epoch));
2090 }
2091 self.update_last_restart_slot()
2092 });
2093
2094 let (_, fill_sysvar_cache_time_us) = measure_us!(
2095 self.transaction_processor
2096 .fill_missing_sysvar_cache_entries(self)
2097 );
2098
2099 PrepareBlockExecutionStats {
2100 update_epoch_time_us,
2101 distribute_rewards_time_us,
2102 cache_preparation_time_us,
2103 update_sysvars_time_us,
2104 fill_sysvar_cache_time_us,
2105 }
2106 }
2107
2108 pub(crate) fn new_from_snapshot(
2110 bank_rc: BankRc,
2111 genesis_config: &GenesisConfig,
2112 runtime_config: Arc<RuntimeConfig>,
2113 fields: BankFieldsToDeserialize,
2114 leader_for_tests: Option<SlotLeader>,
2115 debug_keys: Option<Arc<HashSet<Pubkey>>>,
2116 accounts_data_size_initial: u64,
2117 epoch_stakes: HashMap<Epoch, VersionedEpochStakes>,
2118 ) -> Self {
2119 let now = Instant::now();
2120 let slot = fields.slot;
2121 let epoch = fields.epoch_schedule.get_epoch(slot);
2122 let ancestors = Ancestors::from(vec![slot]);
2123 let rewards_calculation_thread_pool = rewards_calculation_thread_pool();
2126 let (stakes, stakes_time) = measure_time!(
2137 Stakes::load_from_deserialized_delegations(fields.stakes, |pubkey| {
2138 let (account, _slot) = bank_rc
2139 .accounts
2140 .load_with_fixed_root_do_not_populate_read_cache(&ancestors, pubkey)?;
2141 Some(account)
2142 })
2143 .expect(
2144 "Stakes cache is inconsistent with accounts-db. This can indicate a corrupted \
2145 snapshot or bugs in cached accounts or accounts-db.",
2146 )
2147 );
2148 info!("Loading Stakes took: {stakes_time}");
2149 assert!(
2150 fields.versioned_epoch_stakes.is_empty(),
2151 "should be already converted and passed in epoch_stakes parameter"
2152 );
2153 assert!(
2154 !epoch_stakes.is_empty(),
2155 "should be populated (from fields.versioned_epoch_stakes)"
2156 );
2157
2158 let compute_leader = || {
2160 if slot == 0 {
2161 stakes
2164 .highest_staked_node()
2165 .expect("genesis snapshot should contain at least one staked vote account")
2166 } else {
2167 Self::slot_leader_from_epoch_stakes(
2168 fields.slot,
2169 &fields.epoch_schedule,
2170 &epoch_stakes,
2171 )
2172 }
2173 };
2174 #[cfg(not(feature = "dev-context-only-utils"))]
2175 let leader = {
2176 _ = leader_for_tests;
2177 compute_leader()
2178 };
2179 #[cfg(feature = "dev-context-only-utils")]
2180 let leader = leader_for_tests.unwrap_or_else(compute_leader);
2181 assert_eq!(
2182 fields.leader_id, leader.id,
2183 "snapshot leader_id does not match computed slot leader"
2184 );
2185
2186 let stakes_accounts_load_duration = now.elapsed();
2187 let rent = Self::load_rent_from_account_for_snapshot_load(&bank_rc.accounts, &ancestors);
2188 let partitioned_rewards_stake_account_stores_per_block = bank_rc
2189 .accounts
2190 .accounts_db
2191 .partitioned_epoch_rewards_config
2192 .stake_account_stores_per_block;
2193 let mut bank = Self {
2194 rc: bank_rc,
2195 status_cache: Arc::<RwLock<BankStatusCache>>::default(),
2196 store_transaction_signatures_in_status_cache: !runtime_config
2197 .skip_transaction_signatures_in_status_cache,
2198 blockhash_queue: RwLock::new(fields.blockhash_queue),
2199 max_processing_age: MAX_PROCESSING_AGE,
2200 partitioned_rewards_stake_account_stores_per_block,
2201 ancestors,
2202 hash: RwLock::new(fields.hash),
2203 parent_hash: fields.parent_hash,
2204 parent_slot: fields.parent_slot,
2205 hard_forks: Arc::new(RwLock::new(fields.hard_forks)),
2206 transaction_count: AtomicU64::new(fields.transaction_count),
2207 non_vote_transaction_count_since_restart: AtomicU64::default(),
2208 transaction_error_count: AtomicU64::default(),
2209 transaction_entries_count: AtomicU64::default(),
2210 transactions_per_entry_max: AtomicU64::default(),
2211 entry_bytes_consumed: EntryBytesBudget::new(DEFAULT_MAX_ENTRY_BYTES_PER_SLOT),
2212 tick_height: AtomicU64::new(fields.tick_height),
2213 signature_count: AtomicU64::new(fields.signature_count),
2214 capitalization: AtomicU64::new(fields.capitalization),
2215 max_tick_height: fields.max_tick_height,
2216 hashes_per_tick: RwLock::new(fields.hashes_per_tick),
2217 ticks_per_slot: fields.ticks_per_slot,
2218 ns_per_slot: fields.ns_per_slot,
2219 genesis_creation_time: fields.genesis_creation_time,
2220 slots_per_year: fields.slots_per_year,
2221 slot_params: SlotParamsArchive::default(),
2222 slot,
2223 bank_id: 0,
2224 epoch,
2225 block_height: fields.block_height,
2226 leader,
2227 fee_rate_governor: fields.fee_rate_governor,
2228 rent_collector: RentCollector::new(
2229 epoch,
2230 fields.epoch_schedule.clone(),
2231 fields.slots_per_year,
2232 rent,
2233 ),
2234 epoch_schedule: fields.epoch_schedule,
2235 inflation: Arc::new(RwLock::new(fields.inflation)),
2236 stakes_cache: StakesCache::new(stakes),
2237 epoch_stakes,
2238 is_delta: AtomicBool::new(fields.is_delta),
2239 rewards: RwLock::new(vec![]),
2240 cluster_type: Some(genesis_config.cluster_type),
2241 transaction_debug_keys: debug_keys,
2242 transaction_log_collector_config: Arc::<RwLock<TransactionLogCollectorConfig>>::default(
2243 ),
2244 transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
2245 feature_set: Arc::<FeatureSet>::default(),
2246 reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
2247 drop_callback: RwLock::new(OptionalDropCallback(None)),
2248 freeze_started: AtomicBool::new(fields.hash != Hash::default()),
2249 vote_only_bank: false,
2250 should_replay_from_blockstore: true,
2251 cost_tracker: RwLock::new(CostTracker::default()),
2252 accounts_data_size_initial,
2253 accounts_data_size_delta_on_chain: AtomicI64::new(0),
2254 accounts_data_size_delta_off_chain: AtomicI64::new(0),
2255 epoch_reward_status: EpochRewardStatus::default(),
2256 transaction_processor: TransactionBatchProcessor::default(),
2257 collector_fee_details: RwLock::new(CollectorFeeDetails::default()),
2259 compute_budget: runtime_config.compute_budget,
2260 transaction_account_lock_limit: runtime_config.transaction_account_lock_limit,
2261 fee_structure: FeeStructure::default(),
2262 #[cfg(feature = "dev-context-only-utils")]
2263 hash_overrides: Arc::new(Mutex::new(HashOverrides::default())),
2264 accounts_lt_hash: Mutex::new(fields.accounts_lt_hash),
2265 accounts_lt_hash_async_progress: Arc::new(AccountsLtHashAsyncProgress::new()),
2266 block_id: RwLock::new(fields.block_id),
2267 bank_hash_stats: AtomicBankHashStats::new(&fields.bank_hash_stats),
2268 epoch_rewards_calculation_cache: Arc::new(Mutex::new(HashMap::default())),
2269 expected_bank_hash: RwLock::new(None),
2270 block_component_processor: RwLock::new(BlockComponentProcessor::default()),
2271 is_alpenglow: AtomicBool::new(false),
2272 transaction_execution_gate: CachePadded::new(TransactionExecutionGate::default()),
2273 };
2274
2275 if bank.get_alpenglow_genesis_certificate().is_some() {
2276 bank.set_is_alpenglow();
2277 }
2278
2279 assert_eq!(
2284 bank.genesis_creation_time, genesis_config.creation_time,
2285 "Bank snapshot genesis creation time does not match genesis.bin creation time. The \
2286 snapshot and genesis.bin might pertain to different clusters"
2287 );
2288 assert_eq!(bank.ticks_per_slot, genesis_config.ticks_per_slot);
2289 assert_eq!(bank.max_tick_height, (bank.slot + 1) * bank.ticks_per_slot);
2290 assert_eq!(bank.epoch_schedule, genesis_config.epoch_schedule);
2291
2292 bank.refresh_slot_params_from_snapshot(genesis_config);
2293 bank.initialize_after_snapshot_restore(|| rewards_calculation_thread_pool);
2294
2295 datapoint_info!(
2296 "bank-new-from-fields",
2297 (
2298 "accounts_data_len-from-snapshot",
2299 fields.accounts_data_len as i64,
2300 i64
2301 ),
2302 (
2303 "accounts_data_len-from-generate_index",
2304 accounts_data_size_initial as i64,
2305 i64
2306 ),
2307 (
2308 "stakes_accounts_load_duration_us",
2309 stakes_accounts_load_duration.as_micros(),
2310 i64
2311 ),
2312 );
2313 bank
2314 }
2315
2316 fn slot_leader_from_epoch_stakes(
2318 slot: Slot,
2319 epoch_schedule: &EpochSchedule,
2320 epoch_stakes: &HashMap<Epoch, VersionedEpochStakes>,
2321 ) -> SlotLeader {
2322 let (epoch, slot_index) = epoch_schedule.get_epoch_and_slot_index(slot);
2323 let epoch_vote_accounts = epoch_stakes
2324 .get(&epoch)
2325 .expect("epoch stakes should contain current epoch")
2326 .stakes()
2327 .vote_accounts();
2328 let leader_schedule =
2329 leader_schedule_from_vote_accounts(epoch, epoch_schedule, epoch_vote_accounts.as_ref())
2330 .expect("leader schedule should be computable from epoch stakes");
2331 leader_schedule.get_slot_leader_at_index(slot_index as usize)
2332 }
2333
2334 pub(crate) fn get_fields_to_serialize(&self) -> BankFieldsToSerialize {
2336 BankFieldsToSerialize {
2337 blockhash_queue: self.blockhash_queue.read().unwrap().clone(),
2338 hash: *self.hash.read().unwrap(),
2339 parent_hash: self.parent_hash,
2340 parent_slot: self.parent_slot,
2341 hard_forks: self.hard_forks.read().unwrap().clone(),
2342 transaction_count: self.transaction_count.load(Relaxed),
2343 tick_height: self.tick_height.load(Relaxed),
2344 signature_count: self.signature_count.load(Relaxed),
2345 capitalization: self.capitalization.load(Relaxed),
2346 max_tick_height: self.max_tick_height,
2347 hashes_per_tick: *self.hashes_per_tick.read().unwrap(),
2348 ticks_per_slot: self.ticks_per_slot,
2349 ns_per_slot: self.ns_per_slot,
2350 genesis_creation_time: self.genesis_creation_time,
2351 slots_per_year: self.slots_per_year,
2352 slot: self.slot,
2353 block_height: self.block_height,
2354 leader_id: self.leader.id,
2355 fee_rate_governor: self.fee_rate_governor.clone(),
2356 epoch_schedule: self.epoch_schedule.clone(),
2357 inflation: *self.inflation.read().unwrap(),
2358 stakes: self.stakes_cache.stakes().clone(),
2359 is_delta: self.is_delta.load(Relaxed),
2360 accounts_data_len: self.load_accounts_data_size(),
2361 versioned_epoch_stakes: self.epoch_stakes.clone(),
2362 accounts_lt_hash: self.accounts_lt_hash.lock().unwrap().clone(),
2363 block_id: self.block_id().expect("block id must be set"),
2364 }
2365 }
2366
2367 pub fn leader(&self) -> &SlotLeader {
2368 &self.leader
2369 }
2370
2371 pub fn leader_id(&self) -> &Pubkey {
2372 &self.leader.id
2373 }
2374
2375 pub fn genesis_creation_time(&self) -> UnixTimestamp {
2376 self.genesis_creation_time
2377 }
2378
2379 pub fn slot(&self) -> Slot {
2380 self.slot
2381 }
2382
2383 pub fn bank_id(&self) -> BankId {
2384 self.bank_id
2385 }
2386
2387 pub fn epoch(&self) -> Epoch {
2388 self.epoch
2389 }
2390
2391 pub fn first_normal_epoch(&self) -> Epoch {
2392 self.epoch_schedule().first_normal_epoch
2393 }
2394
2395 pub fn freeze_lock(&self) -> RwLockReadGuard<'_, Hash> {
2396 self.hash.read().unwrap()
2397 }
2398
2399 pub fn try_enter_transaction_execution(&self) -> Option<TxExecutionGuard<'_>> {
2401 if self
2406 .transaction_execution_gate
2407 .quiesce_requested
2408 .load(Acquire)
2409 {
2410 return None;
2411 }
2412 let lock_guard = self.transaction_execution_gate.lock.read().unwrap();
2413
2414 if self
2418 .transaction_execution_gate
2419 .quiesce_requested
2420 .load(Acquire)
2421 {
2422 None
2423 } else {
2424 Some(TxExecutionGuard {
2425 bank: self,
2426 _lock_guard: lock_guard,
2427 })
2428 }
2429 }
2430
2431 pub fn wait_for_inflight_commits(&self) {
2436 drop(self.hash.write().unwrap());
2437 }
2438
2439 pub fn quiesce_transaction_execution(&self) {
2441 self.transaction_execution_gate
2443 .quiesce_requested
2444 .store(true, Release);
2445 drop(self.transaction_execution_gate.lock.write().unwrap());
2447 self.wait_for_inflight_commits();
2449 }
2450
2451 pub fn hash(&self) -> Hash {
2452 *self.hash.read().unwrap()
2453 }
2454
2455 pub fn is_frozen(&self) -> bool {
2456 *self.hash.read().unwrap() != Hash::default()
2457 }
2458
2459 pub fn freeze_started(&self) -> bool {
2460 self.freeze_started.load(Relaxed)
2461 }
2462
2463 pub fn status_cache_ancestors(&self) -> Vec<u64> {
2464 let (min, mut ancestors) = {
2465 let status_cache = self.status_cache.read().unwrap();
2466 let roots = status_cache.roots();
2467 let mut ancestors = Vec::with_capacity(roots.len() + self.ancestors.len());
2468 let mut min = Slot::MAX;
2469 for root in roots {
2470 ancestors.push(*root);
2471 min = min.min(*root);
2472 }
2473 (if roots.is_empty() { 0 } else { min }, ancestors)
2474 };
2475
2476 ancestors.extend(self.ancestors.iter().filter(|ancestor| *ancestor >= min));
2477 ancestors.sort_unstable();
2478 ancestors.dedup();
2479 ancestors
2480 }
2481
2482 pub fn unix_timestamp_from_genesis(&self) -> i64 {
2484 self.genesis_creation_time.saturating_add(
2485 (self.slot as u128)
2486 .saturating_mul(self.ns_per_slot)
2487 .saturating_div(1_000_000_000) as i64,
2488 )
2489 }
2490
2491 pub fn epoch_stakes_from_slot(&self, slot: Slot) -> Option<&VersionedEpochStakes> {
2493 let epoch = self.epoch_schedule().get_epoch(slot);
2494 self.epoch_stakes(epoch)
2495 }
2496
2497 pub fn get_rank_map(&self, slot: Slot) -> Option<&Arc<BLSPubkeyToRankMap>> {
2499 self.epoch_stakes_from_slot(slot)
2500 .map(|stake| stake.bls_pubkey_to_rank_map())
2501 }
2502
2503 fn update_sysvar_account<F>(&self, pubkey: &Pubkey, updater: F)
2504 where
2505 F: Fn(&Option<AccountSharedData>) -> AccountSharedData,
2506 {
2507 let old_account = self.get_account_with_fixed_root(pubkey);
2508 let mut new_account = updater(&old_account);
2509
2510 self.adjust_sysvar_balance_for_rent(&mut new_account);
2516 self.store_account_and_update_capitalization(pubkey, &new_account);
2517 }
2518
2519 fn inherit_specially_retained_account_fields(
2520 &self,
2521 old_account: &Option<AccountSharedData>,
2522 ) -> InheritableAccountFields {
2523 const RENT_UNADJUSTED_INITIAL_BALANCE: u64 = 1;
2524
2525 (
2526 old_account
2527 .as_ref()
2528 .map(|a| a.lamports())
2529 .unwrap_or(RENT_UNADJUSTED_INITIAL_BALANCE),
2530 old_account
2531 .as_ref()
2532 .map(|a| a.rent_epoch())
2533 .unwrap_or(INITIAL_RENT_EPOCH),
2534 )
2535 }
2536
2537 pub fn clock(&self) -> sysvar::clock::Clock {
2538 from_account(&self.get_account(&sysvar::clock::id()).unwrap_or_default())
2539 .unwrap_or_default()
2540 }
2541
2542 fn update_clock(&self, parent_epoch: Option<Epoch>) {
2543 let mut unix_timestamp = self.clock().unix_timestamp;
2544 let epoch_start_timestamp = {
2546 let epoch = if let Some(epoch) = parent_epoch {
2547 epoch
2548 } else {
2549 self.epoch()
2550 };
2551 let first_slot_in_epoch = self.epoch_schedule().get_first_slot_in_epoch(epoch);
2552 Some((first_slot_in_epoch, self.clock().epoch_start_timestamp))
2553 };
2554 let max_allowable_drift = MaxAllowableDrift {
2555 fast: MAX_ALLOWABLE_DRIFT_PERCENTAGE_FAST,
2556 slow: MAX_ALLOWABLE_DRIFT_PERCENTAGE_SLOW_V2,
2557 };
2558
2559 let ancestor_timestamp = self.clock().unix_timestamp;
2560 if let Some(timestamp_estimate) =
2561 self.get_timestamp_estimate(max_allowable_drift, epoch_start_timestamp)
2562 {
2563 unix_timestamp = timestamp_estimate;
2564 if timestamp_estimate < ancestor_timestamp {
2565 unix_timestamp = ancestor_timestamp;
2566 }
2567 }
2568 datapoint_info!(
2569 "bank-timestamp-correction",
2570 ("slot", self.slot(), i64),
2571 ("from_genesis", self.unix_timestamp_from_genesis(), i64),
2572 ("corrected", unix_timestamp, i64),
2573 ("ancestor_timestamp", ancestor_timestamp, i64),
2574 );
2575 let mut epoch_start_timestamp =
2576 if parent_epoch.is_some() && parent_epoch.unwrap() != self.epoch() {
2578 unix_timestamp
2579 } else {
2580 self.clock().epoch_start_timestamp
2581 };
2582 if self.slot == 0 {
2583 unix_timestamp = self.unix_timestamp_from_genesis();
2584 epoch_start_timestamp = self.unix_timestamp_from_genesis();
2585 }
2586 let clock = sysvar::clock::Clock {
2587 slot: self.slot,
2588 epoch_start_timestamp,
2589 epoch: self.epoch_schedule().get_epoch(self.slot),
2590 leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
2591 unix_timestamp,
2592 };
2593 self.update_sysvar_account(&sysvar::clock::id(), |account| {
2594 create_account(
2595 &clock,
2596 self.inherit_specially_retained_account_fields(account),
2597 )
2598 });
2599 }
2600
2601 fn update_clock_slot_for_alpenglow(&self) {
2610 let clock = self.clock();
2611 let epoch_start_timestamp = match (self.slot, self.parent()) {
2612 (0, _) => self.unix_timestamp_from_genesis(),
2613 (_, Some(parent)) if parent.epoch() != self.epoch() => clock.unix_timestamp,
2614 _ => clock.epoch_start_timestamp,
2615 };
2616 let clock = sysvar::clock::Clock {
2617 slot: self.slot,
2618 epoch: self.epoch_schedule().get_epoch(self.slot),
2619 leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
2620 epoch_start_timestamp,
2621 unix_timestamp: clock.unix_timestamp,
2622 };
2623 self.update_sysvar_account(&sysvar::clock::id(), |account| {
2624 create_account(
2625 &clock,
2626 self.inherit_specially_retained_account_fields(account),
2627 )
2628 });
2629 }
2630
2631 pub fn update_last_restart_slot(&self) {
2632 let current_last_restart_slot = self
2634 .get_account(&sysvar::last_restart_slot::id())
2635 .and_then(|account| {
2636 let lrs: Option<LastRestartSlot> = from_account(&account);
2637 lrs
2638 })
2639 .map(|account| account.last_restart_slot);
2640
2641 let last_restart_slot = {
2642 let slot = self.slot;
2643 let hard_forks_r = self.hard_forks.read().unwrap();
2644
2645 hard_forks_r
2648 .iter()
2649 .rev()
2650 .find(|(hard_fork, _)| *hard_fork <= slot)
2651 .map(|(slot, _)| *slot)
2652 .unwrap_or(0)
2653 };
2654
2655 if current_last_restart_slot != Some(last_restart_slot) {
2657 self.update_sysvar_account(&sysvar::last_restart_slot::id(), |account| {
2658 create_account(
2659 &LastRestartSlot { last_restart_slot },
2660 self.inherit_specially_retained_account_fields(account),
2661 )
2662 });
2663 }
2664 }
2665
2666 pub fn set_sysvar_for_tests<T>(&self, sysvar: &T)
2667 where
2668 T: Serialize + SysvarId,
2669 {
2670 self.update_sysvar_account(&T::id(), |account| {
2671 create_account_with_bincode(
2672 sysvar,
2673 self.inherit_specially_retained_account_fields(account),
2674 )
2675 });
2676 self.transaction_processor
2679 .reset_and_fill_sysvar_cache_entries(self);
2680 }
2681
2682 fn update_slot_history(&self) {
2683 self.update_sysvar_account(&sysvar::slot_history::id(), |account| {
2684 let mut slot_history = account
2685 .as_ref()
2686 .map(|account| wincode::deserialize::<SlotHistory>(account.data()).unwrap())
2687 .unwrap_or_default();
2688 slot_history.add(self.slot());
2689 create_account(
2690 &slot_history,
2691 self.inherit_specially_retained_account_fields(account),
2692 )
2693 });
2694 }
2695
2696 fn update_slot_hashes(&self) {
2697 self.update_sysvar_account(&sysvar::slot_hashes::id(), |account| {
2698 let mut slot_hashes = account
2699 .as_ref()
2700 .map(|account| wincode::deserialize::<SlotHashes>(account.data()).unwrap())
2701 .unwrap_or_default();
2702 slot_hashes.add(self.parent_slot, self.parent_hash);
2703 create_account(
2704 &slot_hashes,
2705 self.inherit_specially_retained_account_fields(account),
2706 )
2707 });
2708 }
2709
2710 pub fn get_slot_history(&self) -> Option<SlotHistory> {
2711 wincode::deserialize::<SlotHistory>(self.get_account(&sysvar::slot_history::id())?.data())
2712 .ok()
2713 }
2714
2715 fn update_epoch_stakes(
2716 &mut self,
2717 leader_schedule_epoch: Epoch,
2718 prefiltered_distribution_vote_accounts: Option<VoteAccounts>,
2719 ) {
2720 if !self.epoch_stakes.contains_key(&leader_schedule_epoch) {
2724 self.epoch_stakes.retain(|&epoch, _| {
2725 epoch >= leader_schedule_epoch.saturating_sub(MAX_LEADER_SCHEDULE_STAKES - 1)
2728 });
2729 let stakes = match prefiltered_distribution_vote_accounts {
2735 Some(prefiltered) => Stakes::new(prefiltered, self.epoch()),
2736 None => self.get_top_epoch_stakes(),
2737 };
2738 let stakes = SerdeStakesToStakeFormat::from(stakes);
2739 let new_epoch_stakes = VersionedEpochStakes::new(stakes, leader_schedule_epoch);
2740 info!(
2741 "new epoch stakes, epoch: {}, total_stake: {}",
2742 leader_schedule_epoch,
2743 new_epoch_stakes.total_stake(),
2744 );
2745
2746 self.maybe_burn_vat_from_staked_accounts(&new_epoch_stakes);
2747
2748 if log::log_enabled!(log::Level::Trace) {
2751 let vote_stakes: HashMap<_, _> = self
2752 .stakes_cache
2753 .stakes()
2754 .vote_accounts()
2755 .delegated_stakes()
2756 .map(|(pubkey, stake)| (*pubkey, stake))
2757 .collect();
2758 trace!("new epoch stakes, stakes: {vote_stakes:#?}");
2759 }
2760 self.epoch_stakes
2761 .insert(leader_schedule_epoch, new_epoch_stakes);
2762 }
2763 }
2764
2765 fn maybe_burn_vat_from_staked_accounts(&mut self, epoch_stakes: &VersionedEpochStakes) {
2770 let feature_snapshot = self.feature_set.snapshot();
2771 if !feature_snapshot.alpenglow {
2772 return;
2773 }
2774
2775 let vat_to_burn_per_epoch = self.vat_to_burn_per_epoch();
2776 let vote_accounts = epoch_stakes.stakes().vote_accounts();
2777 debug_assert!(vote_accounts.len() <= 2000);
2778 let mut accounts_to_store: Vec<(Pubkey, AccountSharedData)> =
2780 Vec::with_capacity(vote_accounts.len() + 1);
2781 let mut total_vat = 0u64;
2782
2783 for (vote_pubkey, _stake) in vote_accounts.delegated_stakes() {
2786 let mut account = self.get_account(vote_pubkey).unwrap();
2787 total_vat += vat_to_burn_per_epoch;
2788 account.set_lamports(
2789 account
2790 .lamports()
2791 .checked_sub(vat_to_burn_per_epoch)
2792 .expect(
2793 "Vote accounts should have already been filtered to contain enough \
2794 balance for the VAT",
2795 ),
2796 );
2797 accounts_to_store.push((*vote_pubkey, account));
2798 }
2799
2800 let mut incinerator_account = self.get_account(&incinerator::id()).unwrap_or_default();
2802 incinerator_account.set_lamports(
2803 incinerator_account
2804 .lamports()
2805 .checked_add(total_vat)
2806 .unwrap(),
2807 );
2808 accounts_to_store.push((incinerator::id(), incinerator_account));
2809
2810 self.store_accounts((self.slot, accounts_to_store.as_slice()), None);
2811 info!(
2812 "Transferred total VAT of {total_vat} lamports to incinerator from staked vote \
2813 accounts"
2814 );
2815 }
2816
2817 #[cfg(feature = "dev-context-only-utils")]
2818 pub fn set_epoch_stakes_for_test(&mut self, epoch: Epoch, stakes: VersionedEpochStakes) {
2819 self.epoch_stakes.insert(epoch, stakes);
2820 }
2821
2822 fn update_rent(&self) {
2823 self.update_sysvar_account(&sysvar::rent::id(), |account| {
2824 create_account(
2825 &self.rent_collector.rent,
2826 self.inherit_specially_retained_account_fields(account),
2827 )
2828 });
2829 }
2830
2831 fn update_epoch_schedule(&self) {
2832 self.update_sysvar_account(&sysvar::epoch_schedule::id(), |account| {
2833 create_account(
2834 self.epoch_schedule(),
2835 self.inherit_specially_retained_account_fields(account),
2836 )
2837 });
2838 }
2839
2840 fn update_stake_history(&self, epoch: Option<Epoch>) {
2841 if epoch == Some(self.epoch()) {
2842 return;
2843 }
2844 self.update_sysvar_account(&stake_history::id(), |account| {
2846 create_account::<StakeHistory>(
2847 self.stakes_cache.stakes().history(),
2848 self.inherit_specially_retained_account_fields(account),
2849 )
2850 });
2851 }
2852
2853 fn refresh_slot_params(&mut self) {
2855 self.refresh_slot_params_with_baseline(self.slot_params.baseline_params());
2856 }
2857
2858 fn refresh_slot_params_from_snapshot(&mut self, genesis_config: &GenesisConfig) {
2859 let (feature_set, _) = self.compute_active_feature_set(false);
2860 self.refresh_slot_params_with_baseline(
2861 self.snapshot_restore_slot_params_baseline(genesis_config, &feature_set),
2862 );
2863 }
2864
2865 fn refresh_slot_params_with_baseline(&mut self, baseline_params: SlotParams) {
2870 self.slot_params =
2871 SlotParamsArchive::new(&self.feature_set, &self.epoch_schedule, baseline_params);
2872 }
2873
2874 fn genesis_config_slot_params(
2876 genesis_config: &GenesisConfig,
2877 partitioned_rewards_stake_account_stores_per_block: u64,
2878 ) -> SlotParams {
2879 SlotParams::genesis_baseline(
2880 genesis_config.ns_per_slot(),
2881 genesis_config.slots_per_year(),
2882 genesis_config.hashes_per_tick(),
2883 partitioned_rewards_stake_account_stores_per_block,
2884 )
2885 }
2886
2887 fn restored_bank_slot_params(&self) -> SlotParams {
2893 SlotParams::genesis_baseline(
2894 self.ns_per_slot,
2895 self.slots_per_year,
2896 self.hashes_per_tick(),
2897 self.partitioned_rewards_stake_account_stores_per_block,
2898 )
2899 }
2900
2901 fn any_slot_time_reduction_effective(
2906 &self,
2907 feature_set: &FeatureSet,
2908 ns_per_slot: u128,
2909 ) -> bool {
2910 SlotParamsArchive::any_slot_time_reduction_effective(
2911 &self.epoch_schedule,
2912 self.slot,
2913 feature_set,
2914 ns_per_slot,
2915 )
2916 }
2917
2918 fn snapshot_restore_slot_params_baseline(
2926 &self,
2927 genesis_config: &GenesisConfig,
2928 feature_set: &FeatureSet,
2929 ) -> SlotParams {
2930 if self.any_slot_time_reduction_effective(feature_set, genesis_config.ns_per_slot()) {
2931 Self::genesis_config_slot_params(
2932 genesis_config,
2933 self.partitioned_rewards_stake_account_stores_per_block,
2934 )
2935 } else {
2936 self.restored_bank_slot_params()
2940 }
2941 }
2942
2943 fn slot_params_at_slot(&self, slot: Slot) -> SlotParams {
2945 self.slot_params.params_at_slot(slot)
2946 }
2947
2948 fn current_slot_params(&self) -> SlotParams {
2950 self.slot_params_at_slot(self.slot)
2951 }
2952
2953 pub(crate) fn vat_to_burn_per_epoch(&self) -> u64 {
2955 self.current_slot_params().vat_to_burn_per_epoch()
2956 }
2957
2958 pub fn get_vat_health_for_next_epoch(
2959 &self,
2960 vote_account_pubkey: &Pubkey,
2961 ) -> std::result::Result<(), VATHealthError> {
2962 let vote_accounts = self.vote_accounts();
2963
2964 let Some((_, vote_account)) = vote_accounts.get(vote_account_pubkey) else {
2965 return Err(VATHealthError::VoteAccountNotFound);
2966 };
2967
2968 if vote_account
2969 .vote_state_view()
2970 .bls_pubkey_compressed()
2971 .is_none()
2972 {
2973 return Err(VATHealthError::NoBLSPubkey);
2974 }
2975
2976 let my_balance = vote_account.lamports();
2977 let minimum_required_balance = self
2978 .minimum_vote_account_balance_for_vat()
2979 .saturating_add(vote_account.vote_state_view().pending_delegator_rewards());
2980 if vote_account.lamports() < minimum_required_balance {
2981 return Err(VATHealthError::InsufficientFundsInVoteAccount(
2982 my_balance,
2983 minimum_required_balance,
2984 ));
2985 }
2986
2987 Ok(())
2988 }
2989
2990 pub fn ns_per_slot_at_slot(&self, slot: Slot) -> u128 {
2992 self.slot_params_at_slot(slot).ns_per_slot()
2993 }
2994
2995 fn slots_per_year_for_epoch(&self, epoch: Epoch) -> f64 {
2997 let first_slot = self.epoch_schedule().get_first_slot_in_epoch(epoch);
2998 self.slot_params_at_slot(first_slot).slots_per_year()
2999 }
3000
3001 fn slot_range_duration_in_years(&self, start_slot: Slot, end_slot: Slot) -> f64 {
3003 if start_slot >= end_slot {
3004 return 0.0;
3005 }
3006
3007 let mut cursor = start_slot;
3008 let mut params = self.slot_params.baseline_params();
3009 let mut duration = 0.0;
3010
3011 for (effective_slot, effective_params) in self.slot_params.param_transitions() {
3012 if effective_slot <= start_slot {
3013 params = effective_params;
3014 continue;
3015 }
3016 if effective_slot >= end_slot {
3017 break;
3018 }
3019
3020 duration += (effective_slot - cursor) as f64 / params.slots_per_year();
3021 cursor = effective_slot;
3022 params = effective_params;
3023 }
3024
3025 duration + (end_slot - cursor) as f64 / params.slots_per_year()
3026 }
3027
3028 pub fn slot_range_duration_nanos(&self, start_slot: Slot, end_slot: Slot) -> u128 {
3030 self.slot_params
3031 .slot_range_duration_nanos(start_slot, end_slot)
3032 }
3033
3034 pub fn epoch_duration_in_years(&self, epoch: Epoch) -> f64 {
3035 self.epoch_schedule().get_slots_in_epoch(epoch) as f64
3039 / self.slots_per_year_for_epoch(epoch)
3040 }
3041
3042 pub fn max_processing_age(&self) -> usize {
3043 self.max_processing_age
3044 }
3045
3046 fn get_inflation_start_slot(&self) -> Slot {
3052 let mut slots = self
3053 .feature_set
3054 .full_inflation_features_enabled()
3055 .iter()
3056 .filter_map(|id| self.feature_set.activated_slot(id))
3057 .collect::<Vec<_>>();
3058 slots.sort_unstable();
3059 slots.first().cloned().unwrap_or_else(|| {
3060 self.feature_set
3061 .activated_slot(&feature_set::pico_inflation::id())
3062 .unwrap_or(0)
3063 })
3064 }
3065
3066 fn get_inflation_num_slots(&self) -> u64 {
3068 let inflation_start_slot = self.inflation_start_slot_aligned_to_rewards();
3069 self.epoch_schedule().get_first_slot_in_epoch(self.epoch()) - inflation_start_slot
3070 }
3071
3072 fn inflation_start_slot_aligned_to_rewards(&self) -> Slot {
3074 let inflation_activation_slot = self.get_inflation_start_slot();
3075 self.epoch_schedule().get_first_slot_in_epoch(
3076 self.epoch_schedule()
3077 .get_epoch(inflation_activation_slot)
3078 .saturating_sub(1),
3079 )
3080 }
3081
3082 pub fn slot_in_year_for_inflation(&self) -> f64 {
3084 let num_slots = self.get_inflation_num_slots();
3085 let inflation_start_slot = self.inflation_start_slot_aligned_to_rewards();
3086 self.slot_range_duration_in_years(inflation_start_slot, inflation_start_slot + num_slots)
3087 }
3088
3089 pub(crate) fn calculate_epoch_inflation_rewards(
3092 &self,
3093 capitalization: u64,
3094 epoch: Epoch,
3095 ) -> u64 {
3096 let slot_in_year = self.slot_in_year_for_inflation();
3097 let validator_rate = self.inflation.read().unwrap().validator(slot_in_year);
3098 let epoch_duration_in_years = self.epoch_duration_in_years(epoch);
3099 (validator_rate * capitalization as f64 * epoch_duration_in_years) as u64
3100 }
3101
3102 fn update_recent_blockhashes_locked(&self, locked_blockhash_queue: &BlockhashQueue) {
3103 #[expect(deprecated)]
3104 self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
3105 let recent_blockhash_iter = locked_blockhash_queue.get_recent_blockhashes();
3106 recent_blockhashes_account::create_account_with_data_and_fields(
3107 recent_blockhash_iter,
3108 self.inherit_specially_retained_account_fields(account),
3109 )
3110 });
3111 }
3112
3113 pub fn update_recent_blockhashes(&self) {
3114 let blockhash_queue = self.blockhash_queue.read().unwrap();
3115 self.update_recent_blockhashes_locked(&blockhash_queue);
3116 }
3117
3118 fn get_timestamp_estimate(
3119 &self,
3120 max_allowable_drift: MaxAllowableDrift,
3121 epoch_start_timestamp: Option<(Slot, UnixTimestamp)>,
3122 ) -> Option<UnixTimestamp> {
3123 let mut get_timestamp_estimate_time = Measure::start("get_timestamp_estimate");
3124 let slots_per_epoch = self.epoch_schedule().slots_per_epoch;
3125 let vote_accounts = self.vote_accounts();
3126 let recent_timestamps = vote_accounts.iter().filter_map(|(pubkey, (_, account))| {
3127 let vote_state = account.vote_state_view();
3128 let last_timestamp = vote_state.last_timestamp();
3129 let slot_delta = self.slot().checked_sub(last_timestamp.slot)?;
3130 (slot_delta <= slots_per_epoch)
3131 .then_some((*pubkey, (last_timestamp.slot, last_timestamp.timestamp)))
3132 });
3133 let elapsed_slot_duration = |from_slot: Slot, to_slot: Slot| {
3134 if from_slot >= to_slot {
3135 Duration::ZERO
3136 } else {
3137 Duration::from_nanos_u128(
3138 self.slot_range_duration_nanos(from_slot.saturating_add(1), to_slot),
3139 )
3140 }
3141 };
3142 let epoch = self.epoch_schedule().get_epoch(self.slot());
3143 let stakes = self.epoch_vote_accounts(epoch)?;
3144 let stake_weighted_timestamp = calculate_stake_weighted_timestamp(
3145 recent_timestamps,
3146 stakes,
3147 self.slot(),
3148 elapsed_slot_duration,
3149 epoch_start_timestamp,
3150 max_allowable_drift,
3151 );
3152 get_timestamp_estimate_time.stop();
3153 datapoint_info!(
3154 "bank-timestamp",
3155 (
3156 "get_timestamp_estimate_us",
3157 get_timestamp_estimate_time.as_us(),
3158 i64
3159 ),
3160 );
3161 stake_weighted_timestamp
3162 }
3163
3164 pub fn rehash(&self) {
3172 let mut hash = self.hash.write().unwrap();
3173 let new = self.hash_internal_state();
3174 if new != *hash {
3175 warn!("Updating bank hash to {new}");
3176 *hash = new;
3177 }
3178 }
3179
3180 pub fn freeze(&self) {
3181 let mut hash = self.hash.write().unwrap();
3193 if *hash == Hash::default() {
3194 self.distribute_transaction_fee_details();
3196 self.update_slot_history();
3197 self.run_incinerator();
3198
3199 self.freeze_started.store(true, Relaxed);
3201 self.finish_accounts_lt_hash_updates();
3204 *hash = self.hash_internal_state();
3205 self.rc.accounts.accounts_db.mark_slot_frozen(self.slot());
3206 }
3207 }
3208
3209 pub fn freeze_and_verify_bank_hash(&self) -> std::result::Result<(), (Hash, Hash)> {
3212 self.freeze();
3213 let computed_hash = self.hash();
3214
3215 if let Some(expected_hash) = self.expected_bank_hash()
3216 && expected_hash != computed_hash
3217 {
3218 return Err((expected_hash, computed_hash));
3219 }
3220 Ok(())
3221 }
3222
3223 pub fn set_expected_bank_hash(&self, hash: Hash) {
3226 *self.expected_bank_hash.write().unwrap() = Some(hash);
3227 }
3228
3229 pub fn expected_bank_hash(&self) -> Option<Hash> {
3231 *self.expected_bank_hash.read().unwrap()
3232 }
3233
3234 #[cfg(feature = "dev-context-only-utils")]
3236 pub fn unfreeze_for_ledger_tool(&self) {
3237 self.freeze_started.store(false, Relaxed);
3238 }
3239
3240 pub fn epoch_schedule(&self) -> &EpochSchedule {
3241 &self.epoch_schedule
3242 }
3243
3244 pub fn squash(&self) -> SquashTiming {
3250 self.freeze();
3251
3252 let mut roots = Vec::with_capacity(self.ancestors.len());
3254 roots.push(self.slot());
3255 roots.extend(self.parents_iter().map(|parent| parent.slot()));
3256
3257 let mut total_cache_us = 0;
3258
3259 let mut squash_accounts_time = Measure::start("squash_accounts_time");
3260 for slot in roots.iter().rev() {
3261 let add_root_timing = self.rc.accounts.add_root(*slot);
3263 total_cache_us += add_root_timing.cache_us;
3264 }
3265 squash_accounts_time.stop();
3266
3267 *self.rc.parent.write().unwrap() = None;
3268
3269 let mut squash_cache_time = Measure::start("squash_cache_time");
3270 self.status_cache
3271 .write()
3272 .unwrap()
3273 .add_roots(roots.iter().copied());
3274 squash_cache_time.stop();
3275
3276 SquashTiming {
3277 squash_accounts_ms: squash_accounts_time.as_ms(),
3278 squash_accounts_cache_ms: total_cache_us / 1000,
3279 squash_cache_ms: squash_cache_time.as_ms(),
3280 }
3281 }
3282
3283 pub fn parent(&self) -> Option<Arc<Bank>> {
3285 self.rc.parent.read().unwrap().clone()
3286 }
3287
3288 pub fn parent_slot(&self) -> Slot {
3289 self.parent_slot
3290 }
3291
3292 pub fn parent_hash(&self) -> Hash {
3293 self.parent_hash
3294 }
3295
3296 fn process_genesis_config(
3297 &mut self,
3298 genesis_config: &GenesisConfig,
3299 #[cfg(feature = "dev-context-only-utils")] leader_for_tests: Option<SlotLeader>,
3300 #[cfg(feature = "dev-context-only-utils")] genesis_hash: Option<Hash>,
3301 ) {
3302 self.fee_rate_governor = genesis_config.fee_rate_governor.clone();
3304
3305 for (pubkey, account) in genesis_config.accounts.iter() {
3306 assert!(
3307 self.get_account(pubkey).is_none(),
3308 "{pubkey} repeated in genesis config"
3309 );
3310 let account_shared_data = create_account_shared_data(account);
3311 self.store_account_without_stakes_cache(pubkey, &account_shared_data);
3312 self.capitalization.fetch_add(account.lamports(), Relaxed);
3313 self.accounts_data_size_initial += account.data().len() as u64;
3314 }
3315
3316 for (pubkey, account) in genesis_config.rewards_pools.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.accounts_data_size_initial += account.data().len() as u64;
3324 }
3325
3326 self.stakes_cache = StakesCache::new(Stakes::new_from_accounts_for_genesis(
3327 self.new_warmup_cooldown_rate_epoch(),
3328 genesis_config.accounts.iter(),
3329 self.use_fixed_point_stake_math(),
3330 ));
3331
3332 let leader = self.stakes_cache.stakes().highest_staked_node();
3336 #[cfg(feature = "dev-context-only-utils")]
3338 let leader = leader_for_tests
3339 .or(leader)
3340 .or(Some(SlotLeader::new_unique()));
3341 self.leader = leader.expect("genesis processing failed because no staked nodes exist");
3342
3343 #[cfg(not(feature = "dev-context-only-utils"))]
3344 let genesis_hash = genesis_config.hash();
3345 #[cfg(feature = "dev-context-only-utils")]
3346 let genesis_hash = genesis_hash.unwrap_or(genesis_config.hash());
3347
3348 self.blockhash_queue.write().unwrap().genesis_hash(
3349 &genesis_hash,
3350 genesis_config.fee_rate_governor.lamports_per_signature,
3351 );
3352
3353 self.hashes_per_tick = RwLock::new(genesis_config.hashes_per_tick());
3354 self.ticks_per_slot = genesis_config.ticks_per_slot();
3355 self.ns_per_slot = genesis_config.ns_per_slot();
3356 self.genesis_creation_time = genesis_config.creation_time;
3357 self.max_tick_height = (self.slot + 1) * self.ticks_per_slot;
3358 self.slots_per_year = genesis_config.slots_per_year();
3359
3360 self.epoch_schedule = genesis_config.epoch_schedule.clone();
3361 self.refresh_slot_params_with_baseline(Self::genesis_config_slot_params(
3362 genesis_config,
3363 self.partitioned_rewards_stake_account_stores_per_block,
3364 ));
3365
3366 self.inflation = Arc::new(RwLock::new(genesis_config.inflation));
3367
3368 self.rent_collector = RentCollector::new(
3369 self.epoch,
3370 self.epoch_schedule().clone(),
3371 self.slots_per_year,
3372 genesis_config.rent.clone(),
3373 );
3374 }
3375
3376 fn burn_and_purge_account(&self, program_id: &Pubkey, mut account: AccountSharedData) {
3377 let old_data_size = account.data().len();
3378 self.capitalization.fetch_sub(account.lamports(), Relaxed);
3379 account.set_lamports(0);
3382 account.data_as_mut_slice().fill(0);
3383 self.store_account(program_id, &account);
3384 self.calculate_and_update_accounts_data_size_delta_off_chain(old_data_size, 0);
3385 }
3386
3387 pub fn add_precompiled_account(&self, program_id: &Pubkey) {
3389 self.add_precompiled_account_with_owner(program_id, native_loader::id())
3390 }
3391
3392 fn add_precompiled_account_with_owner(&self, program_id: &Pubkey, owner: Pubkey) {
3394 if let Some(account) = self.get_account_with_fixed_root(program_id) {
3395 if account.executable() {
3396 return;
3397 } else {
3398 self.burn_and_purge_account(program_id, account);
3400 }
3401 };
3402
3403 assert!(
3404 !self.freeze_started(),
3405 "Can't change frozen bank by adding not-existing new precompiled program \
3406 ({program_id}). Maybe, inconsistent program activation is detected on snapshot \
3407 restore?"
3408 );
3409
3410 let (lamports, rent_epoch) = self.inherit_specially_retained_account_fields(&None);
3412
3413 let account = AccountSharedData::from(Account {
3414 lamports,
3415 owner,
3416 data: vec![],
3417 executable: true,
3418 rent_epoch,
3419 });
3420 self.store_account_and_update_capitalization(program_id, &account);
3421 }
3422
3423 #[allow(deprecated)]
3424 pub fn set_rent_burn_percentage(&mut self, burn_percent: u8) {
3425 self.rent_collector.rent.burn_percent = burn_percent;
3426 }
3427
3428 pub fn set_hashes_per_tick(&self, hashes_per_tick: Option<u64>) {
3429 *self.hashes_per_tick.write().unwrap() = hashes_per_tick;
3430 }
3431
3432 pub fn last_blockhash(&self) -> Hash {
3434 self.blockhash_queue.read().unwrap().last_hash()
3435 }
3436
3437 pub fn last_blockhash_and_lamports_per_signature(&self) -> (Hash, u64) {
3438 let blockhash_queue = self.blockhash_queue.read().unwrap();
3439 let last_hash = blockhash_queue.last_hash();
3440 let last_lamports_per_signature = blockhash_queue
3441 .get_lamports_per_signature(&last_hash)
3442 .unwrap(); (last_hash, last_lamports_per_signature)
3444 }
3445
3446 pub fn is_blockhash_valid(&self, hash: &Hash) -> bool {
3447 let blockhash_queue = self.blockhash_queue.read().unwrap();
3448 blockhash_queue.is_hash_valid_for_age(hash, self.max_processing_age())
3449 }
3450
3451 pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> u64 {
3452 self.rent_collector.rent.minimum_balance(data_len).max(1)
3453 }
3454
3455 pub fn get_lamports_per_signature(&self) -> u64 {
3456 self.fee_rate_governor.lamports_per_signature
3457 }
3458
3459 pub fn fee_features(&self) -> FeeFeatures {
3461 FeeFeatures {}
3462 }
3463
3464 pub fn get_lamports_per_signature_for_blockhash(&self, hash: &Hash) -> Option<u64> {
3465 let blockhash_queue = self.blockhash_queue.read().unwrap();
3466 blockhash_queue.get_lamports_per_signature(hash)
3467 }
3468
3469 pub fn get_fee_for_message(&self, message: &SanitizedMessage) -> Option<u64> {
3470 {
3471 let blockhash_queue = self.blockhash_queue.read().unwrap();
3472 blockhash_queue.get_lamports_per_signature(message.recent_blockhash())
3473 }
3474 .or_else(|| {
3475 let nonce_address = message.get_durable_nonce()?;
3476 let nonce_account = self.get_account_with_fixed_root(nonce_address)?;
3477 verify_nonce_account(&nonce_account, message.recent_blockhash())
3478 .map(|nonce_data| nonce_data.get_lamports_per_signature())
3479 })?;
3480
3481 let transaction_configuration =
3482 TransactionConfiguration::try_from_sanitized_message(message, &self.feature_set)
3483 .ok()?;
3484 Some(solana_fee::calculate_fee(
3485 message,
3486 self.fee_structure().lamports_per_signature,
3487 transaction_configuration.priority_fee_lamports,
3488 self.fee_features(),
3489 ))
3490 }
3491
3492 pub fn get_blockhash_last_valid_block_height(&self, blockhash: &Hash) -> Option<Slot> {
3493 let blockhash_queue = self.blockhash_queue.read().unwrap();
3494 blockhash_queue
3497 .get_hash_age(blockhash)
3498 .map(|age| self.block_height + self.max_processing_age() as u64 - age)
3499 }
3500
3501 pub fn get_alpenglow_genesis_certificate(&self) -> Option<GenesisCert> {
3510 let acct = self.get_account(&GENESIS_CERTIFICATE_ACCOUNT)?;
3511 (!acct.data().is_empty()).then(|| {
3512 let cert: WireBlockCertMessage = wincode::deserialize(acct.data())
3516 .expect("Programmer error deserializing genesis certificate");
3517 GenesisCert {
3518 block: cert.block,
3519 signature: CertSignature {
3520 signature: cert.signature.signature,
3521 bitmap: cert.signature.bitmap,
3522 },
3523 }
3524 })
3525 }
3526
3527 pub fn is_alpenglow(&self) -> bool {
3528 self.is_alpenglow.load(Relaxed)
3529 }
3530
3531 fn set_is_alpenglow(&self) {
3532 self.is_alpenglow.store(true, Relaxed);
3533 }
3534
3535 pub fn set_alpenglow_genesis_certificate(&self, cert: &GenesisCert) {
3537 let cert = WireBlockCertMessage {
3538 block: cert.block,
3539 signature: WireCertSignature {
3540 signature: cert.signature.signature,
3541 bitmap: cert.signature.bitmap.clone(),
3542 },
3543 };
3544 let data = wincode::serialize(&cert).unwrap();
3545 let lamports = Rent::default().minimum_balance(data.len());
3546 let mut cert_acct = AccountSharedData::new(lamports, data.len(), &system_program::ID);
3547 cert_acct.set_data_from_slice(&data);
3548
3549 self.store_account_and_update_capitalization(&GENESIS_CERTIFICATE_ACCOUNT, &cert_acct);
3550 self.set_is_alpenglow();
3551 }
3552
3553 pub fn update_clock_from_footer(&self, unix_timestamp_nanos: i64) {
3556 if !self.feature_set.snapshot().alpenglow {
3557 return;
3558 }
3559
3560 let unix_timestamp_s = unix_timestamp_nanos / 1_000_000_000;
3569 let epoch_start_timestamp = match (self.slot, self.parent()) {
3570 (0, _) => self.unix_timestamp_from_genesis(),
3571 (_, Some(parent)) if parent.epoch() != self.epoch() => unix_timestamp_s,
3572 _ => self.clock().epoch_start_timestamp,
3573 };
3574
3575 let clock = sysvar::clock::Clock {
3579 slot: self.slot,
3580 epoch_start_timestamp,
3581 epoch: self.epoch_schedule().get_epoch(self.slot),
3582 leader_schedule_epoch: self.epoch_schedule().get_leader_schedule_epoch(self.slot),
3583 unix_timestamp: unix_timestamp_s,
3584 };
3585
3586 self.update_sysvar_account(&sysvar::clock::id(), |account| {
3587 create_account(
3588 &clock,
3589 self.inherit_specially_retained_account_fields(account),
3590 )
3591 });
3592
3593 let data = wincode::serialize(&unix_timestamp_nanos).unwrap();
3595 let lamports = Rent::default().minimum_balance(data.len());
3596 let mut alpenclock_acct = AccountSharedData::new(lamports, data.len(), &system_program::ID);
3597 alpenclock_acct.set_data_from_slice(&data);
3598
3599 self.store_account_and_update_capitalization(&NANOSECOND_CLOCK_ACCOUNT, &alpenclock_acct);
3600
3601 self.transaction_processor
3602 .reset_and_fill_sysvar_cache_entries(self);
3603 }
3604
3605 pub fn get_nanosecond_clock(&self) -> Option<i64> {
3608 let acct = self.get_account(&NANOSECOND_CLOCK_ACCOUNT)?;
3609 (!acct.data().is_empty()).then(|| {
3610 wincode::deserialize(acct.data())
3613 .expect("Couldn't deserialize nanosecond resolution clock")
3614 })
3615 }
3616
3617 pub fn confirmed_last_blockhash(&self) -> Hash {
3618 const NUM_BLOCKHASH_CONFIRMATIONS: usize = 3;
3619
3620 let mut last_parent = None;
3621 for (index, parent) in self.parents_iter().enumerate() {
3622 if index == NUM_BLOCKHASH_CONFIRMATIONS {
3623 return parent.last_blockhash();
3624 }
3625 last_parent = Some(parent);
3626 }
3627 last_parent.map_or_else(|| self.last_blockhash(), |parent| parent.last_blockhash())
3628 }
3629
3630 #[cfg(feature = "dev-context-only-utils")]
3632 pub fn clear_signatures(&self) {
3633 self.status_cache.write().unwrap().clear();
3634 }
3635
3636 pub fn clear_slot_signatures(&self, slot: Slot) {
3637 self.status_cache.write().unwrap().clear_slot_entries(slot);
3638 }
3639
3640 fn update_transaction_statuses(
3641 &self,
3642 sanitized_txs: &[impl TransactionWithMeta],
3643 processing_results: &[TransactionProcessingResult],
3644 ) {
3645 let mut status_cache = self.status_cache.write().unwrap();
3646 assert_eq!(sanitized_txs.len(), processing_results.len());
3647 for (tx, processing_result) in sanitized_txs.iter().zip(processing_results) {
3648 if let Ok(processed_tx) = &processing_result {
3649 if processed_tx.nonce_address().is_none() {
3654 status_cache.insert(
3655 tx.recent_blockhash(),
3656 tx.message_hash(),
3657 self.slot(),
3658 processed_tx.status(),
3659 );
3660 }
3661
3662 if self.store_transaction_signatures_in_status_cache {
3663 status_cache.insert(
3666 tx.recent_blockhash(),
3667 tx.signature(),
3668 self.slot(),
3669 processed_tx.status(),
3670 );
3671 }
3672 }
3673 }
3674 }
3675
3676 fn register_recent_blockhash(&self, blockhash: &Hash, scheduler: &InstalledSchedulerRwLock) {
3680 BankWithScheduler::wait_for_paused_scheduler(self, scheduler);
3683
3684 let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3688
3689 #[cfg(feature = "dev-context-only-utils")]
3690 let blockhash_override = self
3691 .hash_overrides
3692 .lock()
3693 .unwrap()
3694 .get_blockhash_override(self.slot())
3695 .copied()
3696 .inspect(|blockhash_override| {
3697 if blockhash_override != blockhash {
3698 info!(
3699 "bank: slot: {}: overrode blockhash: {} with {}",
3700 self.slot(),
3701 blockhash,
3702 blockhash_override
3703 );
3704 }
3705 });
3706 #[cfg(feature = "dev-context-only-utils")]
3707 let blockhash = blockhash_override.as_ref().unwrap_or(blockhash);
3708
3709 w_blockhash_queue.register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3710 self.update_recent_blockhashes_locked(&w_blockhash_queue);
3711 }
3712
3713 pub fn register_unique_recent_blockhash_for_test(&self) {
3716 self.register_recent_blockhash(
3717 &Hash::new_unique(),
3718 &BankWithScheduler::no_scheduler_available(),
3719 )
3720 }
3721
3722 #[cfg(feature = "dev-context-only-utils")]
3723 pub fn register_recent_blockhash_for_test(
3724 &self,
3725 blockhash: &Hash,
3726 lamports_per_signature: Option<u64>,
3727 ) {
3728 let mut w_blockhash_queue = self.blockhash_queue.write().unwrap();
3732 if let Some(lamports_per_signature) = lamports_per_signature {
3733 w_blockhash_queue.register_hash(blockhash, lamports_per_signature);
3734 } else {
3735 w_blockhash_queue
3736 .register_hash(blockhash, self.fee_rate_governor.lamports_per_signature);
3737 }
3738 }
3739
3740 pub fn register_tick(&self, hash: &Hash, scheduler: &InstalledSchedulerRwLock) {
3747 assert!(
3748 !self.freeze_started(),
3749 "register_tick() working on a bank that is already frozen or is undergoing freezing!"
3750 );
3751
3752 if self.is_block_boundary(self.tick_height.load(Relaxed) + 1) {
3753 self.register_recent_blockhash(hash, scheduler);
3754 }
3755
3756 self.tick_height.fetch_add(1, Relaxed);
3762 }
3763
3764 #[cfg(feature = "dev-context-only-utils")]
3765 pub fn register_tick_for_test(&self, hash: &Hash) {
3766 self.register_tick(hash, &BankWithScheduler::no_scheduler_available())
3767 }
3768
3769 #[cfg(feature = "dev-context-only-utils")]
3770 pub fn register_default_tick_for_test(&self) {
3771 self.register_tick_for_test(&Hash::default())
3772 }
3773
3774 pub fn is_complete(&self) -> bool {
3775 self.tick_height() == self.max_tick_height()
3776 }
3777
3778 pub fn is_block_boundary(&self, tick_height: u64) -> bool {
3779 tick_height == self.max_tick_height
3780 }
3781
3782 pub fn get_transaction_account_lock_limit(&self) -> usize {
3784 if let Some(transaction_account_lock_limit) = self.transaction_account_lock_limit {
3785 transaction_account_lock_limit
3786 } else if self.feature_set.snapshot().increase_tx_account_lock_limit {
3787 MAX_TX_ACCOUNT_LOCKS
3788 } else {
3789 64
3790 }
3791 }
3792
3793 pub fn prepare_entry_batch(
3796 &self,
3797 txs: Vec<VersionedTransaction>,
3798 ) -> Result<TransactionBatch<'_, '_, RuntimeTransaction<SanitizedTransaction>>> {
3799 let sanitized_txs = txs
3800 .into_iter()
3801 .map(|tx| {
3802 RuntimeTransaction::try_create(
3803 tx,
3804 MessageHash::Compute,
3805 None,
3806 self,
3807 self.get_reserved_account_keys(),
3808 )
3809 })
3810 .collect::<Result<Vec<_>>>()?;
3811 Ok(TransactionBatch::new(
3812 self.try_lock_accounts(&sanitized_txs),
3813 self,
3814 OwnedOrBorrowed::Owned(sanitized_txs),
3815 ))
3816 }
3817
3818 pub fn try_lock_accounts(&self, txs: &[impl TransactionWithMeta]) -> Vec<Result<()>> {
3820 self.try_lock_accounts_with_results(txs, txs.iter().map(|_| Ok(())))
3821 }
3822
3823 pub fn try_lock_accounts_with_results(
3826 &self,
3827 txs: &[impl TransactionWithMeta],
3828 tx_results: impl Iterator<Item = Result<()>>,
3829 ) -> Vec<Result<()>> {
3830 let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3831
3832 let mut batch_message_hashes = AHashSet::with_capacity(txs.len());
3834 let tx_results = tx_results
3835 .enumerate()
3836 .map(|(i, tx_result)| match tx_result {
3837 Ok(()) => {
3838 if batch_message_hashes.insert(txs[i].message_hash()) {
3840 Ok(())
3841 } else {
3842 Err(TransactionError::AlreadyProcessed)
3843 }
3844 }
3845 Err(e) => Err(e),
3846 });
3847
3848 self.rc
3849 .accounts
3850 .lock_accounts(txs.iter(), tx_results, tx_account_lock_limit)
3851 }
3852
3853 pub fn prepare_sanitized_batch<'a, 'b, Tx: TransactionWithMeta>(
3855 &'a self,
3856 txs: &'b [Tx],
3857 ) -> TransactionBatch<'a, 'b, Tx> {
3858 self.prepare_sanitized_batch_with_results(txs, txs.iter().map(|_| Ok(())))
3859 }
3860
3861 pub fn prepare_sanitized_batch_with_results<'a, 'b, Tx: TransactionWithMeta>(
3864 &'a self,
3865 transactions: &'b [Tx],
3866 transaction_results: impl Iterator<Item = Result<()>>,
3867 ) -> TransactionBatch<'a, 'b, Tx> {
3868 TransactionBatch::new(
3870 self.try_lock_accounts_with_results(transactions, transaction_results),
3871 self,
3872 OwnedOrBorrowed::Borrowed(transactions),
3873 )
3874 }
3875
3876 pub fn prepare_unlocked_batch_from_single_tx<'a, Tx: SVMMessage>(
3878 &'a self,
3879 transaction: &'a Tx,
3880 ) -> TransactionBatch<'a, 'a, Tx> {
3881 let tx_account_lock_limit = self.get_transaction_account_lock_limit();
3882 let lock_result = validate_account_locks(transaction.account_keys(), tx_account_lock_limit);
3883 let mut batch = TransactionBatch::new(
3884 vec![lock_result],
3885 self,
3886 OwnedOrBorrowed::Borrowed(slice::from_ref(transaction)),
3887 );
3888 batch.set_needs_unlock(false);
3889 batch
3890 }
3891
3892 pub fn prepare_locked_batch_from_single_tx<'a, Tx: TransactionWithMeta>(
3894 &'a self,
3895 transaction: &'a Tx,
3896 ) -> TransactionBatch<'a, 'a, Tx> {
3897 self.prepare_sanitized_batch(slice::from_ref(transaction))
3898 }
3899
3900 pub fn resanitize_transaction_minimally(
3901 &self,
3902 transaction: &impl TransactionWithMeta,
3903 sanitized_epoch: Epoch,
3904 alt_invalidation_slot: Slot,
3905 ) -> Result<()> {
3906 if self.vote_only_bank() && !vote_parser::is_valid_vote_only_transaction(transaction) {
3907 return Err(TransactionError::SanitizeFailure);
3908 }
3909
3910 if self.epoch() != sanitized_epoch {
3913 self.check_reserved_keys(transaction)?;
3916
3917 for instr in transaction.instructions_iter() {
3918 if instr.accounts.len() > solana_transaction_context::MAX_ACCOUNTS_PER_INSTRUCTION {
3919 return Err(solana_transaction_error::TransactionError::SanitizeFailure);
3920 }
3921 }
3922 }
3923
3924 if self.slot() > alt_invalidation_slot {
3925 let (_addresses, _deactivation_slot) =
3933 self.load_addresses_from_ref(transaction.message_address_table_lookups())?;
3934 }
3935
3936 Ok(())
3937 }
3938
3939 pub fn simulate_transaction(
3941 &self,
3942 transaction: &impl TransactionWithMeta,
3943 enable_cpi_recording: bool,
3944 ) -> TransactionSimulationResult {
3945 assert!(self.is_frozen(), "simulation bank must be frozen");
3946
3947 self.simulate_transaction_unchecked(transaction, enable_cpi_recording)
3948 }
3949
3950 pub fn simulate_transaction_unchecked(
3953 &self,
3954 transaction: &impl TransactionWithMeta,
3955 enable_cpi_recording: bool,
3956 ) -> TransactionSimulationResult {
3957 let account_keys = transaction.account_keys();
3958 let number_of_accounts = account_keys.len();
3959 let account_overrides = self.get_account_overrides_for_simulation(&account_keys);
3960 let batch = self.prepare_unlocked_batch_from_single_tx(transaction);
3961 let mut timings = ExecuteTimings::default();
3962
3963 let LoadAndExecuteTransactionsOutput {
3964 mut processing_results,
3965 balance_collector,
3966 ..
3967 } = self.load_and_execute_transactions(
3968 &batch,
3969 self.max_processing_age()
3973 .saturating_sub(MAX_TRANSACTION_FORWARDING_DELAY),
3974 &mut timings,
3975 &mut TransactionErrorMetrics::default(),
3976 TransactionProcessingConfig {
3977 account_overrides: Some(&account_overrides),
3978 log_messages_bytes_limit: None,
3979 limit_to_load_programs: true,
3980 recording_config: ExecutionRecordingConfig {
3981 enable_cpi_recording,
3982 enable_log_recording: true,
3983 enable_return_data_recording: true,
3984 enable_transaction_balance_recording: true,
3985 },
3986 drop_on_failure: false,
3987 all_or_nothing: false,
3988 strict_nonce_size_check: true,
3989 drop_noop_transactions: true,
3990 },
3991 );
3992
3993 debug!("simulate_transaction: {timings:?}");
3994
3995 let processing_result = processing_results
3996 .pop()
3997 .unwrap_or(Err(TransactionError::InvalidProgramForExecution));
3998 let (
3999 post_simulation_accounts,
4000 result,
4001 fee,
4002 logs,
4003 return_data,
4004 inner_instructions,
4005 units_consumed,
4006 loaded_accounts_data_size,
4007 ) = match processing_result {
4008 Ok(processed_tx) => {
4009 let executed_units = processed_tx.executed_units();
4010 let loaded_accounts_data_size = processed_tx.loaded_accounts_data_size();
4011
4012 match processed_tx {
4013 ProcessedTransaction::Executed(executed_tx) => {
4014 let details = executed_tx.execution_details;
4015 let post_simulation_accounts = executed_tx
4016 .loaded_transaction
4017 .accounts
4018 .into_iter()
4019 .take(number_of_accounts)
4020 .collect::<Vec<_>>();
4021 (
4022 post_simulation_accounts,
4023 details.status,
4024 Some(executed_tx.loaded_transaction.fee_details.total_fee()),
4025 details.log_messages,
4026 details.return_data,
4027 details.inner_instructions,
4028 executed_units,
4029 loaded_accounts_data_size,
4030 )
4031 }
4032 ProcessedTransaction::FeesOnly(fees_only_tx) => (
4033 vec![],
4034 Err(fees_only_tx.load_error),
4035 Some(fees_only_tx.fee_details.total_fee()),
4036 None,
4037 None,
4038 None,
4039 executed_units,
4040 loaded_accounts_data_size,
4041 ),
4042 ProcessedTransaction::NoOp(no_op_tx) => (
4043 vec![],
4044 Err(no_op_tx.validation_error),
4045 None,
4046 None,
4047 None,
4048 None,
4049 executed_units,
4050 loaded_accounts_data_size,
4051 ),
4052 }
4053 }
4054 Err(error) => (vec![], Err(error), None, None, None, None, 0, 0),
4055 };
4056 let logs = logs.unwrap_or_default();
4057
4058 let (pre_balances, post_balances, pre_token_balances, post_token_balances) =
4059 match balance_collector {
4060 Some(balance_collector) => {
4061 let (mut native_pre, mut native_post, mut token_pre, mut token_post) =
4062 balance_collector.into_vecs();
4063
4064 (
4065 native_pre.pop(),
4066 native_post.pop(),
4067 token_pre.pop(),
4068 token_post.pop(),
4069 )
4070 }
4071 None => (None, None, None, None),
4072 };
4073
4074 TransactionSimulationResult {
4075 result,
4076 logs,
4077 post_simulation_accounts,
4078 units_consumed,
4079 loaded_accounts_data_size,
4080 return_data,
4081 inner_instructions,
4082 fee,
4083 pre_balances,
4084 post_balances,
4085 pre_token_balances,
4086 post_token_balances,
4087 }
4088 }
4089
4090 fn get_account_overrides_for_simulation(&self, account_keys: &AccountKeys) -> AccountOverrides {
4091 let mut account_overrides = AccountOverrides::default();
4092 let slot_history_id = sysvar::slot_history::id();
4093 if account_keys.iter().any(|pubkey| *pubkey == slot_history_id) {
4094 let current_account = self.get_account_with_fixed_root(&slot_history_id);
4095 let slot_history = current_account
4096 .as_ref()
4097 .map(|account| wincode::deserialize::<SlotHistory>(account.data()).unwrap())
4098 .unwrap_or_default();
4099 if slot_history.check(self.slot()) == Check::Found {
4100 let ancestors = Ancestors::from(self.proper_ancestors().collect::<Vec<_>>());
4101 if let Some((account, _)) =
4102 self.load_slow_with_fixed_root(&ancestors, &slot_history_id)
4103 {
4104 account_overrides.set_slot_history(Some(account));
4105 }
4106 }
4107 }
4108 account_overrides
4109 }
4110
4111 pub fn unlock_accounts<'a, Tx: SVMMessage + 'a>(
4112 &self,
4113 txs_and_results: impl Iterator<Item = (&'a Tx, &'a Result<()>)> + Clone,
4114 ) {
4115 self.rc.accounts.unlock_accounts(txs_and_results)
4116 }
4117
4118 pub fn remove_unrooted_slots(&self, slots: &[(Slot, BankId)]) {
4119 self.rc.accounts.accounts_db.remove_unrooted_slots(slots)
4120 }
4121
4122 pub fn get_hash_age(&self, hash: &Hash) -> Option<u64> {
4123 self.blockhash_queue.read().unwrap().get_hash_age(hash)
4124 }
4125
4126 pub fn is_hash_valid_for_age(&self, hash: &Hash, max_age: usize) -> bool {
4127 self.blockhash_queue
4128 .read()
4129 .unwrap()
4130 .is_hash_valid_for_age(hash, max_age)
4131 }
4132
4133 pub fn collect_balances(
4134 &self,
4135 batch: &TransactionBatch<impl SVMMessage>,
4136 ) -> TransactionBalances {
4137 let mut balances: TransactionBalances = vec![];
4138 for transaction in batch.sanitized_transactions() {
4139 let mut transaction_balances: Vec<u64> = vec![];
4140 for account_key in transaction.account_keys().iter() {
4141 transaction_balances.push(self.get_balance(account_key));
4142 }
4143 balances.push(transaction_balances);
4144 }
4145 balances
4146 }
4147
4148 fn cancelled_load_and_execute_tx_batch(
4149 batch: &TransactionBatch<impl TransactionWithMeta>,
4150 ) -> LoadAndExecuteTransactionsOutput {
4151 LoadAndExecuteTransactionsOutput {
4152 processing_results: std::iter::repeat_with(|| Err(TransactionError::CommitCancelled))
4153 .take(batch.sanitized_transactions().len())
4154 .collect(),
4155 processed_counts: ProcessedTransactionCounts::default(),
4156 balance_collector: None,
4157 }
4158 }
4159
4160 pub fn load_and_execute_transactions(
4162 &self,
4163 batch: &TransactionBatch<impl TransactionWithMeta>,
4164 max_age: usize,
4165 timings: &mut ExecuteTimings,
4166 error_counters: &mut TransactionErrorMetrics,
4167 processing_config: TransactionProcessingConfig,
4168 ) -> LoadAndExecuteTransactionsOutput {
4169 let Some(execution_guard) = self.try_enter_transaction_execution() else {
4170 return Self::cancelled_load_and_execute_tx_batch(batch);
4171 };
4172 execution_guard.load_and_execute_transactions(
4173 batch,
4174 max_age,
4175 timings,
4176 error_counters,
4177 processing_config,
4178 )
4179 }
4180
4181 fn do_load_and_execute_transactions(
4182 &self,
4183 batch: &TransactionBatch<impl TransactionWithMeta>,
4184 max_age: usize,
4185 timings: &mut ExecuteTimings,
4186 error_counters: &mut TransactionErrorMetrics,
4187 processing_config: TransactionProcessingConfig,
4188 ) -> LoadAndExecuteTransactionsOutput {
4189 let sanitized_txs = batch.sanitized_transactions();
4190
4191 let (check_results, check_us) = measure_us!(self.check_transactions_before_execution(
4192 sanitized_txs,
4193 batch.lock_results(),
4194 max_age,
4195 error_counters,
4196 ));
4197 timings.saturating_add_in_place(ExecuteTimingType::CheckUs, check_us);
4198
4199 let (blockhash, blockhash_lamports_per_signature) =
4200 self.last_blockhash_and_lamports_per_signature();
4201 let effective_epoch_of_deployments =
4202 self.epoch_schedule().get_epoch(self.slot.saturating_add(
4203 solana_program_runtime::program_cache_entry::DELAY_VISIBILITY_SLOT_OFFSET,
4204 ));
4205 let processing_environment = TransactionProcessingEnvironment {
4206 blockhash,
4207 blockhash_lamports_per_signature,
4208 alpenglow_migration_succeeded: self.is_alpenglow(),
4209 epoch_total_stake: self.get_current_epoch_total_stake(),
4210 feature_set: self.feature_set.runtime_features(),
4211 program_runtime_environments: ProgramRuntimeEnvironments::new(
4212 self.transaction_processor
4213 .program_runtime_environment
4214 .clone(),
4215 self.transaction_processor
4216 .program_runtime_environment_for_epoch(effective_epoch_of_deployments),
4217 ),
4218 rent: self.rent_collector.rent.clone(),
4219 };
4220
4221 let sanitized_output = self
4222 .transaction_processor
4223 .load_and_execute_sanitized_transactions(
4224 self,
4225 sanitized_txs,
4226 check_results,
4227 &processing_environment,
4228 &processing_config,
4229 );
4230
4231 error_counters.accumulate(&sanitized_output.error_metrics);
4233
4234 timings.accumulate(&sanitized_output.execute_timings);
4236
4237 let ((), collect_logs_us) =
4238 measure_us!(self.collect_logs(sanitized_txs, &sanitized_output.processing_results));
4239 timings.saturating_add_in_place(ExecuteTimingType::CollectLogsUs, collect_logs_us);
4240
4241 let mut processed_counts = ProcessedTransactionCounts::default();
4242 let err_count = &mut error_counters.total;
4243
4244 for (processing_result, tx) in sanitized_output
4245 .processing_results
4246 .iter()
4247 .zip(sanitized_txs)
4248 {
4249 if let Some(debug_keys) = &self.transaction_debug_keys {
4250 for key in tx.account_keys().iter() {
4251 if debug_keys.contains(key) {
4252 let result = processing_result.flattened_result();
4253 info!("slot: {} result: {:?} tx: {:?}", self.slot, result, tx);
4254 break;
4255 }
4256 }
4257 }
4258
4259 if processing_result.was_processed() {
4260 processed_counts.signature_count +=
4264 tx.signature_details().num_transaction_signatures();
4265 processed_counts.processed_transactions_count += 1;
4266
4267 if !tx.is_simple_vote_transaction() {
4268 processed_counts.processed_non_vote_transactions_count += 1;
4269 }
4270 }
4271
4272 match processing_result.flattened_result() {
4273 Ok(()) => {
4274 processed_counts.processed_with_successful_result_count += 1;
4275 }
4276 Err(err) => {
4277 if err_count.0 == 0 {
4278 debug!("tx error: {err:?} {tx:?}");
4279 }
4280 *err_count += 1;
4281 }
4282 }
4283 }
4284
4285 LoadAndExecuteTransactionsOutput {
4286 processing_results: sanitized_output.processing_results,
4287 processed_counts,
4288 balance_collector: sanitized_output.balance_collector,
4289 }
4290 }
4291
4292 fn collect_logs(
4293 &self,
4294 transactions: &[impl TransactionWithMeta],
4295 processing_results: &[TransactionProcessingResult],
4296 ) {
4297 let transaction_log_collector_config =
4298 self.transaction_log_collector_config.read().unwrap();
4299 if transaction_log_collector_config.filter == TransactionLogCollectorFilter::None {
4300 return;
4301 }
4302
4303 let collected_logs: Vec<_> = processing_results
4304 .iter()
4305 .zip(transactions)
4306 .filter_map(|(processing_result, transaction)| {
4307 let processed_tx = processing_result.processed_transaction()?;
4309 let execution_details = processed_tx.execution_details()?;
4311 Self::collect_transaction_logs(
4312 &transaction_log_collector_config,
4313 transaction,
4314 execution_details,
4315 )
4316 })
4317 .collect();
4318
4319 if !collected_logs.is_empty() {
4320 let mut transaction_log_collector = self.transaction_log_collector.write().unwrap();
4321 for (log, filtered_mentioned_addresses) in collected_logs {
4322 let transaction_log_index = transaction_log_collector.logs.len();
4323 transaction_log_collector.logs.push(log);
4324 for key in filtered_mentioned_addresses.into_iter() {
4325 transaction_log_collector
4326 .mentioned_address_map
4327 .entry(key)
4328 .or_default()
4329 .push(transaction_log_index);
4330 }
4331 }
4332 }
4333 }
4334
4335 fn collect_transaction_logs(
4336 transaction_log_collector_config: &TransactionLogCollectorConfig,
4337 transaction: &impl TransactionWithMeta,
4338 execution_details: &TransactionExecutionDetails,
4339 ) -> Option<(TransactionLogInfo, Vec<Pubkey>)> {
4340 let log_messages = execution_details.log_messages.as_ref()?;
4342
4343 let mut filtered_mentioned_addresses = Vec::new();
4344 if !transaction_log_collector_config
4345 .mentioned_addresses
4346 .is_empty()
4347 {
4348 for key in transaction.account_keys().iter() {
4349 if transaction_log_collector_config
4350 .mentioned_addresses
4351 .contains(key)
4352 {
4353 filtered_mentioned_addresses.push(*key);
4354 }
4355 }
4356 }
4357
4358 let is_vote = transaction.is_simple_vote_transaction();
4359 let store = match transaction_log_collector_config.filter {
4360 TransactionLogCollectorFilter::All => {
4361 !is_vote || !filtered_mentioned_addresses.is_empty()
4362 }
4363 TransactionLogCollectorFilter::AllWithVotes => true,
4364 TransactionLogCollectorFilter::None => false,
4365 TransactionLogCollectorFilter::OnlyMentionedAddresses => {
4366 !filtered_mentioned_addresses.is_empty()
4367 }
4368 };
4369
4370 if store {
4371 Some((
4372 TransactionLogInfo {
4373 signature: *transaction.signature(),
4374 result: execution_details.status.clone(),
4375 is_vote,
4376 log_messages: log_messages.clone(),
4377 },
4378 filtered_mentioned_addresses,
4379 ))
4380 } else {
4381 None
4382 }
4383 }
4384
4385 pub fn load_accounts_data_size(&self) -> u64 {
4387 self.accounts_data_size_initial
4388 .saturating_add_signed(self.load_accounts_data_size_delta())
4389 }
4390
4391 pub fn load_accounts_data_size_delta(&self) -> i64 {
4393 let delta_on_chain = self.load_accounts_data_size_delta_on_chain();
4394 let delta_off_chain = self.load_accounts_data_size_delta_off_chain();
4395 delta_on_chain.saturating_add(delta_off_chain)
4396 }
4397
4398 pub fn load_accounts_data_size_delta_on_chain(&self) -> i64 {
4401 self.accounts_data_size_delta_on_chain.load(Acquire)
4402 }
4403
4404 pub fn load_accounts_data_size_delta_off_chain(&self) -> i64 {
4407 self.accounts_data_size_delta_off_chain.load(Acquire)
4408 }
4409
4410 fn update_accounts_data_size_delta_on_chain(&self, amount: i64) {
4413 if amount == 0 {
4414 return;
4415 }
4416
4417 self.accounts_data_size_delta_on_chain
4418 .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_on_chain| {
4419 Some(accounts_data_size_delta_on_chain.saturating_add(amount))
4420 })
4421 .unwrap();
4423 }
4424
4425 fn update_accounts_data_size_delta_off_chain(&self, amount: i64) {
4428 if amount == 0 {
4429 return;
4430 }
4431
4432 self.accounts_data_size_delta_off_chain
4433 .fetch_update(AcqRel, Acquire, |accounts_data_size_delta_off_chain| {
4434 Some(accounts_data_size_delta_off_chain.saturating_add(amount))
4435 })
4436 .unwrap();
4438 }
4439
4440 fn calculate_and_update_accounts_data_size_delta_off_chain(
4442 &self,
4443 old_data_size: usize,
4444 new_data_size: usize,
4445 ) {
4446 let data_size_delta = calculate_data_size_delta(old_data_size, new_data_size);
4447 self.update_accounts_data_size_delta_off_chain(data_size_delta);
4448 }
4449
4450 fn filter_program_errors_and_collect_fee_details(
4451 &self,
4452 processing_results: &[TransactionProcessingResult],
4453 ) {
4454 let mut accumulated_fee_details = FeeDetails::default();
4455
4456 processing_results.iter().for_each(|processing_result| {
4457 if let Ok(processed_tx) = processing_result {
4458 accumulated_fee_details.accumulate(&processed_tx.fee_details());
4459 }
4460 });
4461
4462 self.collector_fee_details
4463 .write()
4464 .unwrap()
4465 .accumulate(&accumulated_fee_details);
4466 }
4467
4468 fn update_bank_hash_stats<'a>(&self, accounts: &impl StorableAccounts<'a>) {
4469 let mut stats = BankHashStats::default();
4470 (0..accounts.len()).for_each(|i| {
4471 accounts.account(i, |account| {
4472 stats.update(&account);
4473 })
4474 });
4475 self.bank_hash_stats.accumulate(&stats);
4476 }
4477
4478 pub fn commit_transactions(
4479 &self,
4480 sanitized_txs: &[impl TransactionWithMeta],
4481 processing_results: Vec<TransactionProcessingResult>,
4482 processed_counts: &ProcessedTransactionCounts,
4483 timings: &mut ExecuteTimings,
4484 ) -> Vec<TransactionCommitResult> {
4485 assert!(
4486 !self.freeze_started(),
4487 "commit_transactions() working on a bank that is already frozen or is undergoing \
4488 freezing!"
4489 );
4490
4491 let ProcessedTransactionCounts {
4492 processed_transactions_count,
4493 processed_non_vote_transactions_count,
4494 processed_with_successful_result_count,
4495 signature_count,
4496 } = *processed_counts;
4497
4498 self.increment_transaction_count(processed_transactions_count);
4499 self.increment_non_vote_transaction_count_since_restart(
4500 processed_non_vote_transactions_count,
4501 );
4502 self.increment_signature_count(signature_count);
4503
4504 let processed_with_failure_result_count =
4505 processed_transactions_count.saturating_sub(processed_with_successful_result_count);
4506 self.transaction_error_count
4507 .fetch_add(processed_with_failure_result_count, Relaxed);
4508
4509 if processed_transactions_count > 0 {
4510 self.is_delta.store(true, Relaxed);
4511 self.transaction_entries_count.fetch_add(1, Relaxed);
4512 self.transactions_per_entry_max
4513 .fetch_max(processed_transactions_count, Relaxed);
4514 }
4515
4516 let ((), store_accounts_us) = measure_us!({
4517 let maybe_transaction_refs = self
4521 .accounts()
4522 .accounts_db
4523 .has_accounts_update_notifier()
4524 .then(|| {
4525 sanitized_txs
4526 .iter()
4527 .map(|tx| tx.as_sanitized_transaction())
4528 .collect::<Vec<_>>()
4529 });
4530
4531 let (accounts_to_store, transactions) = collect_accounts_to_store(
4532 sanitized_txs,
4533 &maybe_transaction_refs,
4534 &processing_results,
4535 );
4536
4537 let to_store = (self.slot(), accounts_to_store.as_slice());
4538 self.update_bank_hash_stats(&to_store);
4539 self.enqueue_on_chain_accounts_lt_hash_updates(&to_store);
4540 self.rc.accounts.store_accounts(
4541 to_store,
4542 self.bank_id(),
4543 transactions.as_deref(),
4544 &self.ancestors,
4545 );
4546 });
4547
4548 let ((), update_stakes_cache_us) =
4551 measure_us!(self.update_stakes_cache(sanitized_txs, &processing_results));
4552
4553 let ((), update_executors_us) = measure_us!({
4554 let mut cache = None;
4555 for processing_result in &processing_results {
4556 if let Some(ProcessedTransaction::Executed(executed_tx)) =
4557 processing_result.processed_transaction()
4558 {
4559 let programs_modified_by_tx = &executed_tx.programs_modified_by_tx;
4560 if executed_tx.was_successful() && !programs_modified_by_tx.is_empty() {
4561 cache
4562 .get_or_insert_with(|| {
4563 self.transaction_processor
4564 .global_program_cache
4565 .write()
4566 .unwrap()
4567 })
4568 .merge(
4569 &self.transaction_processor.program_runtime_environment,
4570 self.slot,
4571 programs_modified_by_tx,
4572 );
4573 }
4574 }
4575 }
4576 });
4577
4578 let accounts_data_len_delta = processing_results
4579 .iter()
4580 .filter_map(|processing_result| processing_result.processed_transaction())
4581 .filter_map(|processed_tx| processed_tx.execution_details())
4582 .filter_map(|details| details.accounts_deltas.as_ref())
4583 .map(|deltas| {
4584 deltas
4585 .accounts_resize_delta
4586 .saturating_sub_unsigned(deltas.accounts_uninitialized_size)
4587 })
4588 .sum();
4589 self.update_accounts_data_size_delta_on_chain(accounts_data_len_delta);
4590
4591 let ((), update_transaction_statuses_us) =
4592 measure_us!(self.update_transaction_statuses(sanitized_txs, &processing_results));
4593
4594 self.filter_program_errors_and_collect_fee_details(&processing_results);
4595
4596 timings.saturating_add_in_place(ExecuteTimingType::StoreUs, store_accounts_us);
4597 timings.saturating_add_in_place(
4598 ExecuteTimingType::UpdateStakesCacheUs,
4599 update_stakes_cache_us,
4600 );
4601 timings.saturating_add_in_place(ExecuteTimingType::UpdateExecutorsUs, update_executors_us);
4602 timings.saturating_add_in_place(
4603 ExecuteTimingType::UpdateTransactionStatuses,
4604 update_transaction_statuses_us,
4605 );
4606
4607 Self::create_commit_results(processing_results)
4608 }
4609
4610 fn create_commit_results(
4611 processing_results: Vec<TransactionProcessingResult>,
4612 ) -> Vec<TransactionCommitResult> {
4613 processing_results
4614 .into_iter()
4615 .map(|processing_result| {
4616 let processing_result = processing_result?;
4617 let executed_units = processing_result.executed_units();
4618 let loaded_accounts_data_size = processing_result.loaded_accounts_data_size();
4619
4620 match processing_result {
4621 ProcessedTransaction::Executed(executed_tx) => {
4622 let successful = executed_tx.was_successful();
4623 let execution_details = executed_tx.execution_details;
4624 let LoadedTransaction {
4625 accounts: loaded_accounts,
4626 fee_details,
4627 rollback_accounts,
4628 ..
4629 } = executed_tx.loaded_transaction;
4630
4631 let fee_payer_post_balance = if successful {
4633 loaded_accounts[0].1.lamports()
4634 } else {
4635 rollback_accounts.fee_payer().1.lamports()
4636 };
4637
4638 Ok(CommittedTransaction {
4639 status: execution_details.status,
4640 log_messages: execution_details.log_messages,
4641 inner_instructions: execution_details.inner_instructions,
4642 return_data: execution_details.return_data,
4643 executed_units,
4644 fee_details,
4645 loaded_account_stats: TransactionLoadedAccountsStats {
4646 loaded_accounts_count: loaded_accounts.len(),
4647 loaded_accounts_data_size,
4648 },
4649 fee_payer_post_balance,
4650 })
4651 }
4652 ProcessedTransaction::FeesOnly(fees_only_tx) => Ok(CommittedTransaction {
4653 status: Err(fees_only_tx.load_error),
4654 log_messages: None,
4655 inner_instructions: None,
4656 return_data: None,
4657 executed_units,
4658 fee_details: fees_only_tx.fee_details,
4659 loaded_account_stats: TransactionLoadedAccountsStats {
4660 loaded_accounts_count: fees_only_tx.rollback_accounts.count(),
4661 loaded_accounts_data_size,
4662 },
4663 fee_payer_post_balance: fees_only_tx
4664 .rollback_accounts
4665 .fee_payer()
4666 .1
4667 .lamports(),
4668 }),
4669 ProcessedTransaction::NoOp(no_op_tx) => Ok(CommittedTransaction {
4670 status: Err(no_op_tx.validation_error),
4671 log_messages: None,
4672 inner_instructions: None,
4673 return_data: None,
4674 executed_units,
4675 fee_details: FeeDetails::default(),
4676 loaded_account_stats: TransactionLoadedAccountsStats {
4677 loaded_accounts_count: 0,
4678 loaded_accounts_data_size,
4679 },
4680 fee_payer_post_balance: no_op_tx.fee_payer_balance.unwrap_or(0),
4681 }),
4682 }
4683 })
4684 .collect()
4685 }
4686
4687 fn run_incinerator(&self) {
4688 if let Some((account, _)) =
4689 self.get_account_modified_since_parent_with_fixed_root(&incinerator::id())
4690 {
4691 self.capitalization.fetch_sub(account.lamports(), Relaxed);
4692 self.store_account(&incinerator::id(), &AccountSharedData::default());
4693 }
4694 }
4695
4696 pub(crate) fn get_accounts_for_bank_hash_details(&self) -> Vec<(Pubkey, AccountSharedData)> {
4699 let mut accounts = self
4700 .rc
4701 .accounts
4702 .accounts_db
4703 .get_pubkey_account_for_slot(self.slot());
4704 accounts.sort_unstable_by_key(|a| a.0);
4706 accounts
4707 }
4708
4709 pub fn cluster_type(&self) -> ClusterType {
4710 self.cluster_type.unwrap()
4713 }
4714
4715 #[must_use]
4717 pub fn load_execute_and_commit_transactions(
4718 &self,
4719 batch: &TransactionBatch<impl TransactionWithMeta>,
4720 recording_config: ExecutionRecordingConfig,
4721 timings: &mut ExecuteTimings,
4722 log_messages_bytes_limit: Option<usize>,
4723 ) -> (Vec<TransactionCommitResult>, Option<BalanceCollector>) {
4724 self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4725 batch,
4726 recording_config,
4727 timings,
4728 log_messages_bytes_limit,
4729 None::<fn(&_) -> _>,
4730 )
4731 .unwrap()
4732 }
4733
4734 pub fn load_execute_and_commit_transactions_with_pre_commit_callback(
4735 &self,
4736 batch: &TransactionBatch<impl TransactionWithMeta>,
4737 recording_config: ExecutionRecordingConfig,
4738 timings: &mut ExecuteTimings,
4739 log_messages_bytes_limit: Option<usize>,
4740 pre_commit_callback: impl FnOnce(&[TransactionProcessingResult]) -> Result<()>,
4741 ) -> Result<(Vec<TransactionCommitResult>, Option<BalanceCollector>)> {
4742 self.do_load_execute_and_commit_transactions_with_pre_commit_callback(
4743 batch,
4744 recording_config,
4745 timings,
4746 log_messages_bytes_limit,
4747 Some(pre_commit_callback),
4748 )
4749 }
4750
4751 fn do_load_execute_and_commit_transactions_with_pre_commit_callback(
4752 &self,
4753 batch: &TransactionBatch<impl TransactionWithMeta>,
4754 recording_config: ExecutionRecordingConfig,
4755 timings: &mut ExecuteTimings,
4756 log_messages_bytes_limit: Option<usize>,
4757 pre_commit_callback: Option<impl FnOnce(&[TransactionProcessingResult]) -> Result<()>>,
4758 ) -> Result<(Vec<TransactionCommitResult>, Option<BalanceCollector>)> {
4759 let execution_guard = self.try_enter_transaction_execution();
4760 let LoadAndExecuteTransactionsOutput {
4761 processing_results,
4762 processed_counts,
4763 balance_collector,
4764 } = if let Some(execution_guard) = execution_guard.as_ref() {
4765 execution_guard.load_and_execute_transactions(
4766 batch,
4767 self.max_processing_age(),
4768 timings,
4769 &mut TransactionErrorMetrics::default(),
4770 TransactionProcessingConfig {
4771 account_overrides: None,
4772 log_messages_bytes_limit,
4773 limit_to_load_programs: false,
4774 recording_config,
4775 drop_on_failure: false,
4776 all_or_nothing: false,
4777 strict_nonce_size_check: false,
4778 drop_noop_transactions: false,
4779 },
4780 )
4781 } else {
4782 Self::cancelled_load_and_execute_tx_batch(batch)
4783 };
4784
4785 if let Some(pre_commit_callback) = pre_commit_callback {
4786 let () = pre_commit_callback(&processing_results)?;
4787 }
4788
4789 let commit_results = if let Some(execution_guard) = execution_guard.as_ref() {
4790 execution_guard.commit_transactions(
4791 batch.sanitized_transactions(),
4792 processing_results,
4793 &processed_counts,
4794 timings,
4795 )
4796 } else {
4797 Self::create_commit_results(processing_results)
4798 };
4799 drop(execution_guard);
4800 Ok((commit_results, balance_collector))
4801 }
4802
4803 pub fn process_transaction(&self, tx: &Transaction) -> Result<()> {
4806 self.try_process_transactions(std::iter::once(tx))?[0].clone()
4807 }
4808
4809 pub fn process_transaction_with_metadata(
4812 &self,
4813 tx: impl Into<VersionedTransaction>,
4814 ) -> Result<CommittedTransaction> {
4815 let txs = vec![tx.into()];
4816 let batch = self.prepare_entry_batch(txs)?;
4817
4818 let (mut commit_results, ..) = self.load_execute_and_commit_transactions(
4819 &batch,
4820 ExecutionRecordingConfig {
4821 enable_cpi_recording: false,
4822 enable_log_recording: true,
4823 enable_return_data_recording: true,
4824 enable_transaction_balance_recording: false,
4825 },
4826 &mut ExecuteTimings::default(),
4827 Some(1000 * 1000),
4828 );
4829
4830 commit_results.remove(0)
4831 }
4832
4833 pub fn try_process_transactions<'a>(
4836 &self,
4837 txs: impl Iterator<Item = &'a Transaction>,
4838 ) -> Result<Vec<Result<()>>> {
4839 let txs = txs
4840 .map(|tx| VersionedTransaction::from(tx.clone()))
4841 .collect();
4842 self.try_process_entry_transactions(txs)
4843 }
4844
4845 pub fn try_process_entry_transactions(
4848 &self,
4849 txs: Vec<VersionedTransaction>,
4850 ) -> Result<Vec<Result<()>>> {
4851 let batch = self.prepare_entry_batch(txs)?;
4852 Ok(self.process_transaction_batch(&batch))
4853 }
4854
4855 #[must_use]
4856 fn process_transaction_batch(
4857 &self,
4858 batch: &TransactionBatch<impl TransactionWithMeta>,
4859 ) -> Vec<Result<()>> {
4860 self.load_execute_and_commit_transactions(
4861 batch,
4862 ExecutionRecordingConfig::new_single_setting(false),
4863 &mut ExecuteTimings::default(),
4864 None,
4865 )
4866 .0
4867 .into_iter()
4868 .map(|commit_result| commit_result.and_then(|committed_tx| committed_tx.status))
4869 .collect()
4870 }
4871
4872 pub fn transfer(&self, n: u64, keypair: &Keypair, to: &Pubkey) -> Result<Signature> {
4875 let blockhash = self.last_blockhash();
4876 let tx = system_transaction::transfer(keypair, to, n, blockhash);
4877 let signature = tx.signatures[0];
4878 self.process_transaction(&tx).map(|_| signature)
4879 }
4880
4881 pub fn read_balance(account: &AccountSharedData) -> u64 {
4882 account.lamports()
4883 }
4884 pub fn get_balance(&self, pubkey: &Pubkey) -> u64 {
4887 self.get_account(pubkey)
4888 .map(|x| Self::read_balance(&x))
4889 .unwrap_or(0)
4890 }
4891
4892 pub fn parents(&self) -> Vec<Arc<Bank>> {
4894 self.parents_iter().collect()
4895 }
4896
4897 pub(crate) fn parents_iter(&self) -> impl Iterator<Item = Arc<Bank>> + '_ {
4898 let mut bank = self.parent();
4899 core::iter::from_fn(move || {
4900 let parent = bank.take()?;
4901 bank = parent.parent();
4902 Some(parent)
4903 })
4904 }
4905
4906 pub fn parents_inclusive(self: Arc<Self>) -> Vec<Arc<Bank>> {
4908 let mut parents = Vec::with_capacity(self.ancestors.len());
4909 parents.push(Arc::clone(&self));
4910 parents.extend(self.parents_iter());
4911 parents
4912 }
4913
4914 pub fn store_account(&self, pubkey: &Pubkey, account: &AccountSharedData) {
4917 self.store_accounts((self.slot(), &[(pubkey, account)][..]), None)
4918 }
4919
4920 pub fn store_accounts<'a>(
4926 &self,
4927 accounts: impl StorableAccounts<'a>,
4928 thread_pool_for_loading_accounts: Option<&ThreadPool>,
4929 ) {
4930 assert!(!self.freeze_started());
4931 let mut m = Measure::start("stakes_cache.check_and_store");
4932 let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
4933 let use_fixed_point_stake_math = self.use_fixed_point_stake_math();
4934
4935 (0..accounts.len()).for_each(|i| {
4936 accounts.account(i, |account| {
4937 self.stakes_cache.check_and_store(
4938 account.pubkey(),
4939 &account,
4940 new_warmup_cooldown_rate_epoch,
4941 use_fixed_point_stake_math,
4942 )
4943 })
4944 });
4945 self.store_accounts_without_stakes_cache(accounts, thread_pool_for_loading_accounts);
4946 m.stop();
4947 self.rc
4948 .accounts
4949 .accounts_db
4950 .stats
4951 .stakes_cache_check_and_store_us
4952 .fetch_add(m.as_us(), Relaxed);
4953 }
4954
4955 fn store_account_without_stakes_cache(&self, pubkey: &Pubkey, account: &AccountSharedData) {
4956 self.store_accounts_without_stakes_cache((self.slot(), &[(pubkey, account)][..]), None)
4957 }
4958
4959 fn store_accounts_without_stakes_cache<'a>(
4965 &self,
4966 accounts: impl StorableAccounts<'a>,
4967 thread_pool_for_loading_accounts: Option<&ThreadPool>,
4968 ) {
4969 assert!(!self.freeze_started());
4970 self.update_bank_hash_stats(&accounts);
4971 self.enqueue_off_chain_accounts_lt_hash_updates(
4972 &accounts,
4973 thread_pool_for_loading_accounts,
4974 );
4975 self.rc
4976 .accounts
4977 .store_accounts(accounts, self.bank_id(), None, &self.ancestors);
4978 }
4979
4980 pub fn force_flush_accounts_cache(&self) {
4981 self.rc
4982 .accounts
4983 .accounts_db
4984 .flush_accounts_cache(true, Some(self.slot()))
4985 }
4986
4987 pub(crate) fn store_account_and_update_capitalization(
4990 &self,
4991 pubkey: &Pubkey,
4992 new_account: &AccountSharedData,
4993 ) {
4994 let old_account_data_size = if let Some(old_account) =
4995 self.get_account_with_fixed_root_no_cache(pubkey)
4996 {
4997 match new_account.lamports().cmp(&old_account.lamports()) {
4998 std::cmp::Ordering::Greater => {
4999 let diff = new_account.lamports() - old_account.lamports();
5000 trace!("store_account_and_update_capitalization: increased: {pubkey} {diff}");
5001 self.capitalization.fetch_add(diff, Relaxed);
5002 }
5003 std::cmp::Ordering::Less => {
5004 let diff = old_account.lamports() - new_account.lamports();
5005 trace!("store_account_and_update_capitalization: decreased: {pubkey} {diff}");
5006 self.capitalization.fetch_sub(diff, Relaxed);
5007 }
5008 std::cmp::Ordering::Equal => {}
5009 }
5010 old_account.data().len()
5011 } else {
5012 trace!(
5013 "store_account_and_update_capitalization: created: {pubkey} {}",
5014 new_account.lamports()
5015 );
5016 self.capitalization
5017 .fetch_add(new_account.lamports(), Relaxed);
5018 0
5019 };
5020
5021 self.store_account(pubkey, new_account);
5022
5023 let new_account_data_size = if new_account.lamports() == 0 {
5025 0
5026 } else {
5027 new_account.data().len()
5028 };
5029 self.calculate_and_update_accounts_data_size_delta_off_chain(
5030 old_account_data_size,
5031 new_account_data_size,
5032 );
5033 }
5034
5035 pub fn accounts(&self) -> Arc<Accounts> {
5036 self.rc.accounts.clone()
5037 }
5038
5039 fn apply_cost_tracker_limits_for_active_features(&mut self) {
5041 let params = self.current_slot_params();
5042 let cost_limits =
5043 params.cost_limits(self.feature_set.snapshot().raise_block_limits_to_100m);
5044
5045 let mut cost_tracker = self.write_cost_tracker().unwrap();
5046 cost_tracker.set_limits(cost_limits);
5047 }
5048
5049 fn apply_partitioned_epoch_rewards_config_for_active_features(&mut self) {
5051 self.partitioned_rewards_stake_account_stores_per_block = self
5052 .current_slot_params()
5053 .partitioned_epoch_rewards_stake_account_stores_per_block();
5054 }
5055
5056 fn apply_slot_time_persistent_changes(&mut self) {
5058 let params = self.current_slot_params();
5059 self.ns_per_slot = params.ns_per_slot();
5060 self.slots_per_year = params.slots_per_year();
5061 self.rent_collector.slots_per_year = params.slots_per_year();
5062 if !self.feature_set.is_active(&feature_set::alpenglow::id())
5063 && self.hashes_per_tick().is_some()
5064 {
5065 self.set_hashes_per_tick(params.hashes_per_tick());
5066 }
5067 }
5068
5069 fn assert_bank_matches_slot_params(&self) {
5071 let params = self.current_slot_params();
5072 assert_eq!(
5073 self.ns_per_slot,
5074 params.ns_per_slot(),
5075 "snapshot slot-time ns_per_slot mismatch"
5076 );
5077 assert_eq!(
5078 self.slots_per_year.to_bits(),
5079 params.slots_per_year().to_bits(),
5080 "snapshot slot-time slots_per_year mismatch"
5081 );
5082 assert_eq!(
5083 self.rent_collector.slots_per_year.to_bits(),
5084 params.slots_per_year().to_bits(),
5085 "snapshot slot-time rent_collector.slots_per_year mismatch"
5086 );
5087 let hashes_per_tick = self.hashes_per_tick();
5088 if !self.feature_set.is_active(&feature_set::alpenglow::id()) && hashes_per_tick.is_some() {
5089 assert_eq!(
5090 hashes_per_tick,
5091 params.hashes_per_tick(),
5092 "snapshot slot-time hashes_per_tick mismatch"
5093 );
5094 }
5095 assert_eq!(
5096 self.entry_bytes_budget().slot_limit(),
5097 params.max_entry_bytes_per_slot(),
5098 "snapshot slot-time entry byte budget mismatch"
5099 );
5100 }
5101
5102 fn apply_slot_time_runtime_changes(&mut self) {
5105 self.entry_bytes_consumed =
5106 EntryBytesBudget::new(self.current_slot_params().max_entry_bytes_per_slot());
5107 self.apply_cost_tracker_limits_for_active_features();
5108 self.apply_partitioned_epoch_rewards_config_for_active_features();
5109 }
5110
5111 fn apply_simd_0339_invoke_cost_changes(&mut self) {
5112 let simd_0268_active = self.feature_set.snapshot().raise_cpi_nesting_limit_to_8;
5113 let compute_budget = self
5114 .compute_budget()
5115 .as_ref()
5116 .unwrap_or(&ComputeBudget::new_with_defaults(simd_0268_active))
5117 .to_cost();
5118
5119 self.transaction_processor
5120 .set_execution_cost(compute_budget);
5121 }
5122
5123 fn apply_activated_features(&mut self) {
5125 self.reserved_account_keys = {
5127 let mut reserved_keys = ReservedAccountKeys::clone(&self.reserved_account_keys);
5128 reserved_keys.update_active_set(&self.feature_set);
5129 Arc::new(reserved_keys)
5130 };
5131
5132 self.refresh_slot_params();
5135 self.apply_slot_time_runtime_changes();
5136 self.apply_simd_0339_invoke_cost_changes();
5137
5138 let program_runtime_environment =
5139 self.create_program_runtime_environment(&self.feature_set);
5140 self.transaction_processor
5141 .global_program_cache
5142 .write()
5143 .unwrap()
5144 .latest_root_slot = self.slot;
5145 self.transaction_processor
5146 .epoch_boundary_preparation
5147 .write()
5148 .unwrap()
5149 .upcoming_epoch = self.epoch;
5150 self.transaction_processor.program_runtime_environment = program_runtime_environment;
5151
5152 self.add_active_builtin_programs();
5154 }
5155
5156 fn create_program_runtime_environment(
5157 &self,
5158 feature_set: &FeatureSet,
5159 ) -> ProgramRuntimeEnvironment {
5160 let simd_0268_active = feature_set.snapshot().raise_cpi_nesting_limit_to_8;
5161 let compute_budget = self
5162 .compute_budget()
5163 .as_ref()
5164 .unwrap_or(&ComputeBudget::new_with_defaults(simd_0268_active))
5165 .to_budget();
5166 create_program_runtime_environment(
5167 &feature_set.runtime_features(),
5168 &compute_budget,
5169 false, false, )
5172 .unwrap()
5173 }
5174
5175 pub fn set_tick_height(&self, tick_height: u64) {
5176 self.tick_height.store(tick_height, Relaxed)
5177 }
5178
5179 pub fn set_inflation(&self, inflation: Inflation) {
5180 *self.inflation.write().unwrap() = inflation;
5181 }
5182
5183 pub fn hard_forks(&self) -> HardForks {
5185 self.hard_forks.read().unwrap().clone()
5186 }
5187
5188 pub fn register_hard_fork(&self, new_hard_fork_slot: Slot) {
5189 let bank_slot = self.slot();
5190
5191 let lock = self.freeze_lock();
5192 let bank_frozen = *lock != Hash::default();
5193 if new_hard_fork_slot < bank_slot {
5194 warn!(
5195 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is older than the \
5196 bank at slot {bank_slot} that attempted to register it."
5197 );
5198 } else if (new_hard_fork_slot == bank_slot) && bank_frozen {
5199 warn!(
5200 "Hard fork at slot {new_hard_fork_slot} ignored, the hard fork is the same slot \
5201 as the bank at slot {bank_slot} that attempted to register it, but that bank is \
5202 already frozen."
5203 );
5204 } else {
5205 self.hard_forks
5206 .write()
5207 .unwrap()
5208 .register(new_hard_fork_slot);
5209 }
5210 }
5211
5212 pub fn register_hard_forks(&self, new_hard_fork_slots: Option<&Vec<Slot>>) {
5213 if let Some(slots) = new_hard_fork_slots {
5214 slots
5215 .iter()
5216 .for_each(|hard_fork_slot| self.register_hard_fork(*hard_fork_slot));
5217 }
5218 }
5219
5220 pub fn get_account_with_fixed_root_no_cache(
5221 &self,
5222 pubkey: &Pubkey,
5223 ) -> Option<AccountSharedData> {
5224 self.rc
5225 .accounts
5226 .load_with_fixed_root_do_not_populate_read_cache(&self.ancestors, pubkey)
5227 .map(|(acc, _slot)| acc)
5228 }
5229
5230 pub fn get_account(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
5234 self.get_account_modified_slot(pubkey)
5235 .map(|(acc, _slot)| acc)
5236 }
5237
5238 pub fn get_account_with_fixed_root(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
5245 self.get_account_modified_slot_with_fixed_root(pubkey)
5246 .map(|(acc, _slot)| acc)
5247 }
5248
5249 pub fn get_account_modified_slot_with_fixed_root(
5251 &self,
5252 pubkey: &Pubkey,
5253 ) -> Option<(AccountSharedData, Slot)> {
5254 self.load_slow_with_fixed_root(&self.ancestors, pubkey)
5255 }
5256
5257 pub fn get_account_with_fixed_root_if(
5264 &self,
5265 pubkey: &Pubkey,
5266 load_filter: impl Fn(u64, &Pubkey, usize) -> bool,
5267 ) -> Option<AccountSharedData> {
5268 self.rc
5269 .accounts
5270 .load_with_fixed_root(&self.ancestors, pubkey, Some(load_filter))
5271 .map(|(acc, _slot)| acc)
5272 }
5273
5274 pub fn get_account_modified_slot(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> {
5275 self.load_slow(&self.ancestors, pubkey)
5276 }
5277
5278 fn load_slow(
5279 &self,
5280 ancestors: &Ancestors,
5281 pubkey: &Pubkey,
5282 ) -> Option<(AccountSharedData, Slot)> {
5283 self.rc.accounts.load_without_fixed_root(ancestors, pubkey)
5287 }
5288
5289 fn load_slow_with_fixed_root(
5290 &self,
5291 ancestors: &Ancestors,
5292 pubkey: &Pubkey,
5293 ) -> Option<(AccountSharedData, Slot)> {
5294 self.rc
5295 .accounts
5296 .load_with_fixed_root(ancestors, pubkey, None::<fn(_, &_, _) -> _>)
5297 }
5298
5299 pub fn get_program_accounts(
5300 &self,
5301 program_id: &Pubkey,
5302 ) -> ScanResult<Vec<KeyedAccountSharedData>> {
5303 self.rc
5304 .accounts
5305 .load_by_program(&self.ancestors, self.bank_id, program_id)
5306 }
5307
5308 pub fn get_filtered_program_accounts<F: Fn(&AccountSharedData) -> bool>(
5309 &self,
5310 program_id: &Pubkey,
5311 filter: F,
5312 ) -> ScanResult<Vec<KeyedAccountSharedData>> {
5313 self.rc.accounts.load_by_program_with_filter(
5314 &self.ancestors,
5315 self.bank_id,
5316 program_id,
5317 filter,
5318 )
5319 }
5320
5321 pub fn get_filtered_indexed_accounts<F: Fn(&AccountSharedData) -> bool>(
5322 &self,
5323 index_key: &IndexKey,
5324 filter: F,
5325 byte_limit_for_scan: Option<usize>,
5326 ) -> ScanResult<Vec<KeyedAccountSharedData>> {
5327 self.rc.accounts.load_by_index_key_with_filter(
5328 &self.ancestors,
5329 self.bank_id,
5330 index_key,
5331 filter,
5332 byte_limit_for_scan,
5333 )
5334 }
5335
5336 pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
5337 self.rc.accounts.account_indexes_include_key(key)
5338 }
5339
5340 pub fn scan_all_accounts<F>(&self, scan_func: F) -> ScanResult<()>
5342 where
5343 F: FnMut(Option<(&Pubkey, AccountSharedData, Slot)>),
5344 {
5345 self.rc
5346 .accounts
5347 .scan_all(&self.ancestors, self.bank_id, scan_func)
5348 }
5349
5350 pub fn get_program_accounts_modified_since_parent(
5351 &self,
5352 program_id: &Pubkey,
5353 ) -> Vec<KeyedAccountSharedData> {
5354 self.rc
5355 .accounts
5356 .load_by_program_slot(self.slot(), Some(program_id))
5357 }
5358
5359 pub fn get_transaction_logs(
5360 &self,
5361 address: Option<&Pubkey>,
5362 ) -> Option<Vec<TransactionLogInfo>> {
5363 self.transaction_log_collector
5364 .read()
5365 .unwrap()
5366 .get_logs_for_address(address)
5367 }
5368
5369 pub fn get_all_accounts_modified_since_parent(&self) -> Vec<KeyedAccountSharedData> {
5371 self.rc.accounts.load_by_program_slot(self.slot(), None)
5372 }
5373
5374 fn get_account_modified_since_parent_with_fixed_root(
5376 &self,
5377 pubkey: &Pubkey,
5378 ) -> Option<(AccountSharedData, Slot)> {
5379 let just_self: Ancestors = Ancestors::from(vec![self.slot()]);
5380 if let Some((account, slot)) = self.load_slow_with_fixed_root(&just_self, pubkey)
5381 && slot == self.slot()
5382 {
5383 return Some((account, slot));
5384 }
5385 None
5386 }
5387
5388 pub fn get_largest_accounts(
5389 &self,
5390 num: usize,
5391 filter_by_address: &HashSet<Pubkey>,
5392 filter: AccountAddressFilter,
5393 ) -> ScanResult<Vec<(Pubkey, u64)>> {
5394 self.rc.accounts.load_largest_accounts(
5395 &self.ancestors,
5396 self.bank_id,
5397 num,
5398 filter_by_address,
5399 filter,
5400 )
5401 }
5402
5403 pub fn transaction_count(&self) -> u64 {
5405 self.transaction_count.load(Relaxed)
5406 }
5407
5408 pub fn non_vote_transaction_count_since_restart(&self) -> u64 {
5413 self.non_vote_transaction_count_since_restart.load(Relaxed)
5414 }
5415
5416 pub fn executed_transaction_count(&self) -> u64 {
5418 self.transaction_count()
5419 .saturating_sub(self.parent().map_or(0, |parent| parent.transaction_count()))
5420 }
5421
5422 pub fn transaction_error_count(&self) -> u64 {
5423 self.transaction_error_count.load(Relaxed)
5424 }
5425
5426 pub fn transaction_entries_count(&self) -> u64 {
5427 self.transaction_entries_count.load(Relaxed)
5428 }
5429
5430 pub fn transactions_per_entry_max(&self) -> u64 {
5431 self.transactions_per_entry_max.load(Relaxed)
5432 }
5433
5434 pub fn max_data_shreds_per_slot(&self) -> u32 {
5435 self.max_data_shreds_per_slot_for_slot(self.slot())
5436 }
5437
5438 pub fn max_code_shreds_per_slot(&self) -> u32 {
5439 self.max_code_shreds_per_slot_for_slot(self.slot())
5440 }
5441
5442 pub fn max_data_shreds_per_slot_for_slot(&self, slot: Slot) -> u32 {
5447 self.slot_params_at_slot(slot).max_data_shreds_per_slot()
5448 }
5449
5450 pub fn max_code_shreds_per_slot_for_slot(&self, slot: Slot) -> u32 {
5455 self.slot_params_at_slot(slot).max_code_shreds_per_slot()
5456 }
5457
5458 pub fn max_entry_bytes_per_slot(&self) -> u64 {
5459 self.entry_bytes_budget().slot_limit()
5460 }
5461
5462 pub fn entry_bytes_budget(&self) -> &EntryBytesBudget {
5463 &self.entry_bytes_consumed
5464 }
5465
5466 fn increment_transaction_count(&self, tx_count: u64) {
5467 self.transaction_count.fetch_add(tx_count, Relaxed);
5468 }
5469
5470 fn increment_non_vote_transaction_count_since_restart(&self, tx_count: u64) {
5471 self.non_vote_transaction_count_since_restart
5472 .fetch_add(tx_count, Relaxed);
5473 }
5474
5475 pub fn signature_count(&self) -> u64 {
5476 self.signature_count.load(Relaxed)
5477 }
5478
5479 fn increment_signature_count(&self, signature_count: u64) {
5480 self.signature_count.fetch_add(signature_count, Relaxed);
5481 }
5482
5483 pub fn get_signature_status_processed_since_parent(
5484 &self,
5485 signature: &Signature,
5486 ) -> Option<Result<()>> {
5487 if let Some((slot, status)) = self.get_signature_status_slot(signature)
5488 && slot <= self.slot()
5489 {
5490 return Some(status);
5491 }
5492 None
5493 }
5494
5495 pub fn get_signature_status_with_blockhash(
5496 &self,
5497 signature: &Signature,
5498 blockhash: &Hash,
5499 ) -> Option<Result<()>> {
5500 let rcache = self.status_cache.read().unwrap();
5501 rcache
5502 .get_status(signature, blockhash, &self.ancestors)
5503 .map(|v| v.1)
5504 }
5505
5506 pub fn get_transaction_status_and_slot_from_status_cache(
5507 &self,
5508 message_hash: &Hash,
5509 transaction_blockhash: &Hash,
5510 ) -> Option<(Slot, bool)> {
5511 let rcache = self.status_cache.read().unwrap();
5512 rcache
5513 .get_status(message_hash, transaction_blockhash, &self.ancestors)
5514 .map(|(slot, status)| (slot, status.is_ok()))
5515 }
5516
5517 pub fn get_signature_status_slot(&self, signature: &Signature) -> Option<(Slot, Result<()>)> {
5518 let rcache = self.status_cache.read().unwrap();
5519 rcache.get_status_any_blockhash(signature, &self.ancestors)
5520 }
5521
5522 pub fn get_signature_status(&self, signature: &Signature) -> Option<Result<()>> {
5523 self.get_signature_status_slot(signature).map(|v| v.1)
5524 }
5525
5526 pub fn has_signature(&self, signature: &Signature) -> bool {
5527 self.get_signature_status_slot(signature).is_some()
5528 }
5529
5530 fn hash_internal_state(&self) -> Hash {
5533 let measure_total = Measure::start("");
5534 let slot = self.slot();
5535
5536 let mut hash = hashv(&[
5537 self.parent_hash.as_ref(),
5538 &self.signature_count().to_le_bytes(),
5539 self.last_blockhash().as_ref(),
5540 ]);
5541
5542 let accounts_lt_hash_checksum = {
5543 let accounts_lt_hash = &*self.accounts_lt_hash.lock().unwrap();
5544 let lt_hash_bytes = bytemuck::must_cast_slice(&accounts_lt_hash.0.0);
5545 hash = hashv(&[hash.as_ref(), lt_hash_bytes]);
5546 accounts_lt_hash.0.checksum()
5547 };
5548
5549 let buf = self
5550 .hard_forks
5551 .read()
5552 .unwrap()
5553 .get_hash_data(slot, self.parent_slot());
5554 if let Some(buf) = buf {
5555 let hard_forked_hash = hashv(&[hash.as_ref(), &buf]);
5556 warn!("hard fork at slot {slot} by hashing {buf:?}: {hash} => {hard_forked_hash}");
5557 hash = hard_forked_hash;
5558 }
5559
5560 #[cfg(feature = "dev-context-only-utils")]
5561 let hash_override = self
5562 .hash_overrides
5563 .lock()
5564 .unwrap()
5565 .get_bank_hash_override(slot)
5566 .copied()
5567 .inspect(|&hash_override| {
5568 if hash_override != hash {
5569 info!(
5570 "bank: slot: {}: overrode bank hash: {} with {}",
5571 self.slot(),
5572 hash,
5573 hash_override
5574 );
5575 }
5576 });
5577 #[cfg(feature = "dev-context-only-utils")]
5581 let hash = hash_override.unwrap_or(std::hint::black_box(hash));
5582
5583 let bank_hash_stats = self.bank_hash_stats.load();
5584
5585 let total_us = measure_total.end_as_us();
5586
5587 datapoint_info!(
5588 "bank-hash_internal_state",
5589 ("slot", slot, i64),
5590 ("total_us", total_us, i64),
5591 );
5592 info!(
5593 "bank frozen: {slot} hash: {hash} signature_count: {} last_blockhash: {} \
5594 capitalization: {}, accounts_lt_hash checksum: {accounts_lt_hash_checksum}, stats: \
5595 {bank_hash_stats:?}",
5596 self.signature_count(),
5597 self.last_blockhash(),
5598 self.capitalization(),
5599 );
5600 hash
5601 }
5602
5603 pub fn run_final_hash_calc(&self) {
5606 self.force_flush_accounts_cache();
5607 _ = self.verify_accounts(None);
5609 }
5610
5611 #[must_use]
5624 fn verify_accounts(&self, calculated_accounts_lt_hash: Option<&AccountsLtHash>) -> bool {
5625 let accounts_db = &self.rc.accounts.accounts_db;
5626
5627 fn check_lt_hash(
5628 expected_accounts_lt_hash: &AccountsLtHash,
5629 calculated_accounts_lt_hash: &AccountsLtHash,
5630 ) -> bool {
5631 let is_ok = calculated_accounts_lt_hash == expected_accounts_lt_hash;
5632 if !is_ok {
5633 let expected = expected_accounts_lt_hash.0.checksum();
5634 let calculated = calculated_accounts_lt_hash.0.checksum();
5635 error!(
5636 "Verifying accounts failed: accounts lattice hashes do not match, expected: \
5637 {expected}, calculated: {calculated}",
5638 );
5639 }
5640 is_ok
5641 }
5642
5643 info!("Verifying accounts...");
5644 let start = Instant::now();
5645 let expected_accounts_lt_hash = self.accounts_lt_hash.lock().unwrap().clone();
5646 let is_ok = if let Some(calculated_accounts_lt_hash) = calculated_accounts_lt_hash {
5647 check_lt_hash(&expected_accounts_lt_hash, calculated_accounts_lt_hash)
5648 } else {
5649 let calculated_accounts_lt_hash =
5650 accounts_db.calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors);
5651 check_lt_hash(&expected_accounts_lt_hash, &calculated_accounts_lt_hash)
5652 };
5653 info!("Verifying accounts... Done in {:?}", start.elapsed());
5654 is_ok
5655 }
5656
5657 pub fn get_snapshot_storages(&self, base_slot: Option<Slot>) -> Vec<Arc<AccountStorageEntry>> {
5661 let start_slot = base_slot.map_or(0, |slot| slot.saturating_add(1));
5663 let requested_slots = start_slot..=self.slot();
5665
5666 self.rc.accounts.accounts_db.get_storages(requested_slots).0
5667 }
5668
5669 #[must_use]
5670 fn verify_hash(&self) -> bool {
5671 assert!(self.is_frozen());
5672 let calculated_hash = self.hash_internal_state();
5673 let expected_hash = self.hash();
5674
5675 if calculated_hash == expected_hash {
5676 true
5677 } else {
5678 warn!(
5679 "verify failed: slot: {}, {} (calculated) != {} (expected)",
5680 self.slot(),
5681 calculated_hash,
5682 expected_hash
5683 );
5684 false
5685 }
5686 }
5687
5688 pub fn verify_transaction<D>(
5690 &self,
5691 tx: UnsanitizedTransactionView<D>,
5692 verification_mode: TransactionVerificationMode,
5693 ) -> Result<RuntimeTransaction<ResolvedTransactionView<D>>>
5694 where
5695 D: TransactionData,
5696 {
5697 let enable_tx_v1 = self.feature_set.snapshot().enable_tx_v1;
5699 if !enable_tx_v1 && matches!(tx.version(), TransactionVersion::V1) {
5700 return Err(TransactionError::UnsupportedVersion);
5701 }
5702 let max_transaction_size = match tx.version() {
5703 TransactionVersion::V1 if enable_tx_v1 => solana_message::v1::MAX_TRANSACTION_SIZE,
5704 _ => PACKET_DATA_SIZE,
5705 };
5706
5707 let sanitized_tx = {
5710 let size = tx.data().len();
5711 if size > max_transaction_size {
5712 return Err(TransactionError::SanitizeFailure);
5713 }
5714
5715 let sanitized_tx = tx
5716 .sanitize(&solana_runtime_transaction::sanitize_config::sanitize_config())
5717 .map_err(|_| TransactionError::SanitizeFailure)?;
5718
5719 if verification_mode == TransactionVerificationMode::FullVerification {
5720 let message_data = sanitized_tx.message_data();
5721 let keys = sanitized_tx.static_account_keys().iter();
5722 let signatures = sanitized_tx.signatures().iter();
5723
5724 for (key, signature) in keys.zip(signatures) {
5725 let valid_signature = signature.verify(key.as_ref(), message_data);
5726 if !valid_signature {
5727 return Err(TransactionError::SignatureFailure);
5728 }
5729 }
5730 };
5731
5732 let sanitized_tx = RuntimeTransaction::<SanitizedTransactionView<_>>::try_new(
5733 sanitized_tx,
5734 MessageHash::Compute,
5735 None,
5736 )?;
5737
5738 let (loaded_addresses, _) = self.load_addresses_for_view(&sanitized_tx)?;
5739
5740 RuntimeTransaction::<ResolvedTransactionView<_>>::try_new(
5741 sanitized_tx,
5742 loaded_addresses,
5743 self.get_reserved_account_keys(),
5744 )
5745 }?;
5746
5747 Ok(sanitized_tx)
5748 }
5749
5750 pub fn load_addresses_for_view<D: TransactionData>(
5753 &self,
5754 view: &SanitizedTransactionView<D>,
5755 ) -> std::result::Result<(Option<LoadedAddresses>, Slot), AddressLoaderError> {
5756 match view.version() {
5757 TransactionVersion::Legacy | TransactionVersion::V1 => Ok((None, u64::MAX)),
5758 TransactionVersion::V0 => self
5759 .load_addresses_from_ref(view.address_table_lookup_iter())
5760 .map(|(loaded_addresses, deactivation_slot)| {
5761 (Some(loaded_addresses), deactivation_slot)
5762 }),
5763 }
5764 }
5765
5766 pub fn check_reserved_keys(&self, tx: &impl SVMMessage) -> Result<()> {
5770 let reserved_keys = self.get_reserved_account_keys();
5773 for (index, key) in tx.account_keys().iter().enumerate() {
5774 if tx.is_writable(index) && reserved_keys.contains(key) {
5775 return Err(TransactionError::ResanitizationNeeded);
5776 }
5777 }
5778
5779 Ok(())
5780 }
5781
5782 pub fn calculate_capitalization_for_tests(&self) -> u64 {
5792 self.rc
5793 .accounts
5794 .accounts_db
5795 .calculate_capitalization_at_startup_from_index(&self.ancestors)
5796 }
5797
5798 pub fn set_capitalization_for_tests(&self, capitalization: u64) {
5803 self.capitalization.store(capitalization, Relaxed);
5804 }
5805
5806 pub fn get_snapshot_hash(&self) -> SnapshotHash {
5810 SnapshotHash::new(self.accounts_lt_hash.lock().unwrap().0.checksum())
5811 }
5812
5813 pub fn verify_snapshot_bank(
5816 &self,
5817 skip_shrink: bool,
5818 force_clean: bool,
5819 latest_full_snapshot_slot: Slot,
5820 calculated_accounts_lt_hash: Option<&AccountsLtHash>,
5821 ) -> bool {
5822 let (verified_accounts, verify_accounts_time_us) = measure_us!({
5823 let should_verify_accounts = !self.rc.accounts.accounts_db.skip_initial_hash_calc;
5824 if should_verify_accounts {
5825 self.verify_accounts(calculated_accounts_lt_hash)
5826 } else {
5827 info!("Verifying accounts... Skipped.");
5828 true
5829 }
5830 });
5831
5832 let (_, clean_time_us) = measure_us!({
5833 let should_clean = force_clean || (!skip_shrink && self.slot() > 0);
5834 if should_clean {
5835 info!("Cleaning...");
5836 self.rc
5841 .accounts
5842 .accounts_db
5843 .clean_accounts(latest_full_snapshot_slot, true);
5844 info!("Cleaning... Done.");
5845 } else {
5846 info!("Cleaning... Skipped.");
5847 }
5848 });
5849
5850 let (_, shrink_time_us) = measure_us!({
5851 let should_shrink = !skip_shrink && self.slot() > 0;
5852 if should_shrink {
5853 info!("Shrinking...");
5854 self.rc.accounts.accounts_db.shrink_all_slots(
5855 true,
5856 Some(self.slot()),
5858 );
5859 info!("Shrinking... Done.");
5860 } else {
5861 info!("Shrinking... Skipped.");
5862 }
5863 });
5864
5865 info!("Verifying bank...");
5866 let (verified_bank, verify_bank_time_us) = measure_us!(self.verify_hash());
5867 info!("Verifying bank... Done.");
5868
5869 datapoint_info!(
5870 "verify_snapshot_bank",
5871 ("clean_us", clean_time_us, i64),
5872 ("shrink_us", shrink_time_us, i64),
5873 ("verify_accounts_us", verify_accounts_time_us, i64),
5874 ("verify_bank_us", verify_bank_time_us, i64),
5875 );
5876
5877 verified_accounts && verified_bank
5878 }
5879
5880 pub fn hashes_per_tick(&self) -> Option<u64> {
5882 *self.hashes_per_tick.read().unwrap()
5883 }
5884
5885 pub fn ticks_per_slot(&self) -> u64 {
5887 self.ticks_per_slot
5888 }
5889
5890 pub fn ticks_per_second(&self) -> u64 {
5892 let ticks_per_slot = u128::from(self.ticks_per_slot.max(1));
5893 let ns_per_tick = self.ns_per_slot.saturating_div(ticks_per_slot).max(1);
5894 u64::try_from(1_000_000_000u128.saturating_div(ns_per_tick))
5895 .expect("ticks per second must fit in u64")
5896 }
5897
5898 pub fn slots_per_year(&self) -> f64 {
5900 self.slots_per_year
5901 }
5902
5903 pub fn tick_height(&self) -> u64 {
5905 self.tick_height.load(Relaxed)
5906 }
5907
5908 pub fn inflation(&self) -> Inflation {
5910 *self.inflation.read().unwrap()
5911 }
5912
5913 pub fn rent_collector(&self) -> &RentCollector {
5915 &self.rent_collector
5916 }
5917
5918 pub fn capitalization(&self) -> u64 {
5920 self.capitalization.load(Relaxed)
5921 }
5922
5923 pub fn max_tick_height(&self) -> u64 {
5925 self.max_tick_height
5926 }
5927
5928 pub fn block_height(&self) -> u64 {
5930 self.block_height
5931 }
5932
5933 pub fn get_slots_in_epoch(&self, epoch: Epoch) -> u64 {
5935 self.epoch_schedule().get_slots_in_epoch(epoch)
5936 }
5937
5938 pub fn get_leader_schedule_epoch(&self, slot: Slot) -> Epoch {
5941 self.epoch_schedule().get_leader_schedule_epoch(slot)
5942 }
5943
5944 fn update_stakes_cache(
5946 &self,
5947 txs: &[impl SVMMessage],
5948 processing_results: &[TransactionProcessingResult],
5949 ) {
5950 debug_assert_eq!(txs.len(), processing_results.len());
5951 let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
5952 let use_fixed_point_stake_math = self.use_fixed_point_stake_math();
5953 txs.iter()
5954 .zip(processing_results)
5955 .filter_map(|(tx, processing_result)| {
5956 processing_result
5957 .processed_transaction()
5958 .map(|processed_tx| (tx, processed_tx))
5959 })
5960 .filter_map(|(tx, processed_tx)| {
5961 processed_tx
5962 .executed_transaction()
5963 .map(|executed_tx| (tx, executed_tx))
5964 })
5965 .filter(|(_, executed_tx)| executed_tx.was_successful())
5966 .flat_map(|(tx, executed_tx)| {
5967 let num_account_keys = tx.account_keys().len();
5968 let loaded_tx = &executed_tx.loaded_transaction;
5969 loaded_tx.accounts.iter().take(num_account_keys)
5970 })
5971 .for_each(|(pubkey, account)| {
5972 self.stakes_cache.check_and_store(
5975 pubkey,
5976 account,
5977 new_warmup_cooldown_rate_epoch,
5978 use_fixed_point_stake_math,
5979 );
5980 });
5981 }
5982
5983 pub fn vote_accounts(&self) -> Arc<VoteAccountsHashMap> {
5986 let stakes = self.stakes_cache.stakes();
5987 Arc::from(stakes.vote_accounts())
5988 }
5989
5990 pub fn get_vote_account(&self, vote_account: &Pubkey) -> Option<VoteAccount> {
5992 let stakes = self.stakes_cache.stakes();
5993 let vote_account = stakes.vote_accounts().get(vote_account)?;
5994 Some(vote_account.clone())
5995 }
5996
5997 pub fn current_epoch_stakes(&self) -> &VersionedEpochStakes {
5999 self.epoch_stakes
6002 .get(&self.epoch.saturating_add(1))
6003 .expect("Current epoch stakes must exist")
6004 }
6005
6006 pub fn epoch_stakes(&self, epoch: Epoch) -> Option<&VersionedEpochStakes> {
6008 self.epoch_stakes.get(&epoch)
6009 }
6010
6011 pub fn verify_certificate(
6013 &self,
6014 cert: UnverifiedCertificate,
6015 ) -> std::result::Result<Certificate, CertVerifyError> {
6016 let slot = cert.cert_type.slot();
6017 let epoch_stakes = self
6018 .epoch_stakes_from_slot(slot)
6019 .ok_or(CertVerifyError::MissingRankMap)?;
6020 let key_to_rank_map = epoch_stakes.bls_pubkey_to_rank_map();
6021 let total_stake = key_to_rank_map.total_stake();
6022
6023 let cert =
6024 cert_verify::verify_certificate(cert, key_to_rank_map.len(), total_stake, |rank| {
6025 key_to_rank_map
6026 .get_pubkey_stake_entry(rank)
6027 .map(|entry| (entry.stake, entry.bls_pubkey))
6028 })?;
6029
6030 Ok(cert)
6031 }
6032
6033 pub fn epoch_stakes_map(&self) -> &HashMap<Epoch, VersionedEpochStakes> {
6034 &self.epoch_stakes
6035 }
6036
6037 pub fn current_epoch_staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
6039 self.current_epoch_stakes().stakes().staked_nodes()
6040 }
6041
6042 pub fn epoch_staked_nodes(&self, epoch: Epoch) -> Option<Arc<HashMap<Pubkey, u64>>> {
6044 Some(self.epoch_stakes.get(&epoch)?.stakes().staked_nodes())
6045 }
6046
6047 pub fn epoch_total_stake(&self, epoch: Epoch) -> Option<u64> {
6049 self.epoch_stakes
6050 .get(&epoch)
6051 .map(|epoch_stakes| epoch_stakes.total_stake())
6052 }
6053
6054 pub fn get_current_epoch_total_stake(&self) -> u64 {
6056 self.current_epoch_stakes().total_stake()
6057 }
6058
6059 pub fn epoch_vote_accounts(&self, epoch: Epoch) -> Option<&VoteAccountsHashMap> {
6061 let epoch_stakes = self.epoch_stakes.get(&epoch)?.stakes();
6062 Some(epoch_stakes.vote_accounts().as_ref())
6063 }
6064
6065 pub fn get_current_epoch_vote_accounts(&self) -> &VoteAccountsHashMap {
6067 self.current_epoch_stakes()
6068 .stakes()
6069 .vote_accounts()
6070 .as_ref()
6071 }
6072
6073 pub fn epoch_authorized_voter(&self, vote_account: &Pubkey) -> Option<&Pubkey> {
6076 self.epoch_stakes
6077 .get(&self.epoch)
6078 .expect("Epoch stakes for bank's own epoch must exist")
6079 .epoch_authorized_voters()
6080 .get(vote_account)
6081 }
6082
6083 pub fn epoch_vote_accounts_for_node_id(&self, node_id: &Pubkey) -> Option<&NodeVoteAccounts> {
6086 self.epoch_stakes
6087 .get(&self.epoch)
6088 .expect("Epoch stakes for bank's own epoch must exist")
6089 .node_id_to_vote_accounts()
6090 .get(node_id)
6091 }
6092
6093 pub fn epoch_node_id_to_stake(&self, epoch: Epoch, node_id: &Pubkey) -> Option<u64> {
6095 self.epoch_stakes(epoch)
6096 .and_then(|epoch_stakes| epoch_stakes.node_id_to_stake(node_id))
6097 }
6098
6099 pub fn total_epoch_stake(&self) -> u64 {
6101 self.epoch_stakes
6102 .get(&self.epoch)
6103 .expect("Epoch stakes for bank's own epoch must exist")
6104 .total_stake()
6105 }
6106
6107 pub fn epoch_vote_account_stake(&self, vote_account: &Pubkey) -> u64 {
6109 *self
6110 .epoch_vote_accounts(self.epoch())
6111 .expect("Bank epoch vote accounts must contain entry for the bank's own epoch")
6112 .get(vote_account)
6113 .map(|(stake, _)| stake)
6114 .unwrap_or(&0)
6115 }
6116
6117 pub fn get_epoch_and_slot_index(&self, slot: Slot) -> (Epoch, SlotIndex) {
6123 self.epoch_schedule().get_epoch_and_slot_index(slot)
6124 }
6125
6126 pub fn get_epoch_info(&self) -> EpochInfo {
6127 let absolute_slot = self.slot();
6128 let block_height = self.block_height();
6129 let (epoch, slot_index) = self.get_epoch_and_slot_index(absolute_slot);
6130 let slots_in_epoch = self.get_slots_in_epoch(epoch);
6131 let transaction_count = Some(self.transaction_count());
6132 EpochInfo {
6133 epoch,
6134 slot_index,
6135 slots_in_epoch,
6136 absolute_slot,
6137 block_height,
6138 transaction_count,
6139 }
6140 }
6141
6142 pub fn is_empty(&self) -> bool {
6143 !self.is_delta.load(Relaxed)
6144 }
6145
6146 pub fn add_mockup_builtin(&mut self, program_id: Pubkey, builtin: BuiltinFunctionRegisterer) {
6147 self.add_builtin(
6148 program_id,
6149 "mockup",
6150 ProgramCacheEntry::new_builtin(builtin),
6151 );
6152 }
6153
6154 pub fn add_precompile(&mut self, program_id: &Pubkey) {
6155 debug!("Adding precompiled program {program_id}");
6156 self.add_precompiled_account(program_id);
6157 debug!("Added precompiled program {program_id:?}");
6158 }
6159
6160 pub(crate) fn clean_accounts(&self) {
6165 let highest_slot_to_clean = self.slot().saturating_sub(1);
6172
6173 self.rc
6174 .accounts
6175 .accounts_db
6176 .clean_accounts(highest_slot_to_clean, false);
6177 }
6178
6179 pub fn print_accounts_stats(&self) {
6180 self.rc.accounts.accounts_db.print_accounts_stats("");
6181 }
6182
6183 pub fn shrink_candidate_slots(&self) -> usize {
6184 self.rc
6185 .accounts
6186 .accounts_db
6187 .shrink_candidate_slots(self.epoch_schedule())
6188 }
6189
6190 pub(crate) fn shrink_ancient_slots(&self) {
6191 self.rc
6192 .accounts
6193 .accounts_db
6194 .shrink_ancient_slots(self.epoch_schedule())
6195 }
6196
6197 pub fn read_cost_tracker(&self) -> LockResult<RwLockReadGuard<'_, CostTracker>> {
6198 self.cost_tracker.read()
6199 }
6200
6201 pub fn write_cost_tracker(&self) -> LockResult<RwLockWriteGuard<'_, CostTracker>> {
6202 self.cost_tracker.write()
6203 }
6204
6205 pub fn should_bank_still_be_processing_txs(
6208 bank_creation_time: &Instant,
6209 max_tx_ingestion_nanos: u128,
6210 ) -> bool {
6211 bank_creation_time.elapsed().as_nanos() <= max_tx_ingestion_nanos
6213 }
6214
6215 pub fn deactivate_feature(&mut self, id: &Pubkey) {
6216 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6217 feature_set.deactivate(id);
6218 self.feature_set = Arc::new(feature_set);
6219 self.refresh_slot_params();
6220 }
6221
6222 pub fn activate_feature(&mut self, id: &Pubkey) {
6223 let mut feature_set = Arc::make_mut(&mut self.feature_set).clone();
6224 feature_set.activate(id, 0);
6225 self.feature_set = Arc::new(feature_set);
6226 self.refresh_slot_params();
6227 }
6228
6229 pub fn fill_bank_with_ticks_for_tests(&self) {
6230 self.do_fill_bank_with_ticks_for_tests(&BankWithScheduler::no_scheduler_available())
6231 }
6232
6233 pub(crate) fn do_fill_bank_with_ticks_for_tests(&self, scheduler: &InstalledSchedulerRwLock) {
6234 if self.tick_height.load(Relaxed) < self.max_tick_height {
6235 let last_blockhash = self.last_blockhash();
6236 while self.last_blockhash() == last_blockhash {
6237 self.register_tick(&Hash::new_unique(), scheduler)
6238 }
6239 } else {
6240 warn!("Bank already reached max tick height, cannot fill it with more ticks");
6241 }
6242 }
6243
6244 pub fn get_reserved_account_keys(&self) -> &HashSet<Pubkey> {
6247 &self.reserved_account_keys.active
6248 }
6249
6250 fn initialize_after_snapshot_restore<F, TP>(&mut self, rewards_thread_pool_builder: F)
6253 where
6254 F: FnOnce() -> TP,
6255 TP: std::borrow::Borrow<ThreadPool>,
6256 {
6257 self.transaction_processor =
6258 TransactionBatchProcessor::new_uninitialized(self.slot, self.epoch);
6259 if let Some(compute_budget) = &self.compute_budget {
6260 self.transaction_processor
6261 .set_execution_cost(compute_budget.to_cost());
6262 }
6263
6264 self.compute_and_apply_features_after_snapshot_restore();
6265 self.stakes_cache.refresh_delegated_stakes(
6266 self.new_warmup_cooldown_rate_epoch(),
6267 self.use_fixed_point_stake_math(),
6268 );
6269
6270 self.recalculate_partitioned_rewards_if_active(rewards_thread_pool_builder);
6271
6272 self.transaction_processor
6273 .fill_missing_sysvar_cache_entries(self);
6274 }
6275
6276 fn compute_and_apply_genesis_features(&mut self) {
6278 let feature_set = self.compute_active_feature_set(false).0;
6280 self.feature_set = Arc::new(feature_set);
6281
6282 if self
6285 .feature_set
6286 .snapshot()
6287 .deprecate_rent_exemption_threshold
6288 {
6289 self.rent_collector.deprecate_rent_exemption_threshold();
6290 }
6291
6292 if self
6296 .feature_set
6297 .is_active(&feature_set::double_disinflation_rate::id())
6298 {
6299 self.apply_double_disinflation_rate();
6300 }
6301
6302 self.add_builtin_program_accounts();
6304
6305 self.apply_activated_features();
6306 }
6307
6308 fn apply_double_disinflation_rate(&mut self) {
6311 let year = self.slot_in_year_for_inflation();
6312 let mut inflation = *self.inflation.read().unwrap();
6313 let anchor_rate = inflation.total(year);
6314 let taper = feature_set::double_disinflation_rate::TAPER;
6315 inflation.taper = taper;
6316 inflation.initial = anchor_rate / (1.0 - taper).powf(year);
6317 self.inflation = Arc::new(RwLock::new(inflation));
6321 }
6322
6323 fn compute_and_apply_features_after_snapshot_restore(&mut self) {
6326 let feature_set = self.compute_active_feature_set(false).0;
6328 self.feature_set = Arc::new(feature_set);
6329
6330 self.apply_activated_features();
6331 self.assert_bank_matches_slot_params();
6332 }
6333
6334 fn compute_and_apply_new_feature_activations(&mut self) {
6336 let include_pending = true;
6337 let (feature_set, new_feature_activations) =
6338 self.compute_active_feature_set(include_pending);
6339 self.feature_set = Arc::new(feature_set);
6340 self.refresh_slot_params();
6341
6342 for feature_id in new_feature_activations.iter() {
6344 if let Some(mut account) = self.get_account_with_fixed_root(feature_id)
6345 && let Some(mut feature) = feature::state::from_account(&account)
6346 {
6347 feature.activated_at = Some(self.slot());
6348 if feature::state::to_account(&feature, &mut account).is_some() {
6349 self.store_account(feature_id, &account);
6350 }
6351 info!("Feature {} activated at slot {}", feature_id, self.slot());
6352 }
6353 }
6354
6355 self.reserved_account_keys = {
6357 let mut reserved_keys = ReservedAccountKeys::clone(&self.reserved_account_keys);
6358 reserved_keys.update_active_set(&self.feature_set);
6359 Arc::new(reserved_keys)
6360 };
6361
6362 if new_feature_activations.contains(&feature_set::deprecate_rent_exemption_threshold::id())
6363 {
6364 self.rent_collector.deprecate_rent_exemption_threshold();
6365 self.update_rent();
6366 }
6367
6368 let rent_feature_gates = [
6374 (
6375 feature_set::set_lamports_per_byte_to_6333::id(),
6376 feature_set::set_lamports_per_byte_to_6333::LAMPORTS_PER_BYTE,
6377 ),
6378 (
6379 feature_set::set_lamports_per_byte_to_5080::id(),
6380 feature_set::set_lamports_per_byte_to_5080::LAMPORTS_PER_BYTE,
6381 ),
6382 (
6383 feature_set::set_lamports_per_byte_to_2575::id(),
6384 feature_set::set_lamports_per_byte_to_2575::LAMPORTS_PER_BYTE,
6385 ),
6386 (
6387 feature_set::set_lamports_per_byte_to_1322::id(),
6388 feature_set::set_lamports_per_byte_to_1322::LAMPORTS_PER_BYTE,
6389 ),
6390 (
6391 feature_set::set_lamports_per_byte_to_696::id(),
6392 feature_set::set_lamports_per_byte_to_696::LAMPORTS_PER_BYTE,
6393 ),
6394 ];
6395 for (feature_id, lamports_per_byte) in rent_feature_gates {
6396 if new_feature_activations.contains(&feature_id) {
6397 self.rent_collector.rent.lamports_per_byte = lamports_per_byte;
6398 self.update_rent();
6399 }
6400 }
6401
6402 if new_feature_activations.contains(&feature_set::set_lamports_per_byte_to_6960::id()) {
6407 self.rent_collector.rent.lamports_per_byte =
6408 feature_set::set_lamports_per_byte_to_6960::LAMPORTS_PER_BYTE;
6409 self.update_rent();
6410 }
6411
6412 if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
6413 *self.inflation.write().unwrap() = Inflation::pico();
6414 self.fee_rate_governor.burn_percent = solana_fee_calculator::DEFAULT_BURN_PERCENT;
6415 }
6416
6417 if !new_feature_activations.is_disjoint(&self.feature_set.full_inflation_features_enabled())
6418 {
6419 *self.inflation.write().unwrap() = Inflation::full();
6420 self.fee_rate_governor.burn_percent = solana_fee_calculator::DEFAULT_BURN_PERCENT;
6421 }
6422
6423 if new_feature_activations.contains(&feature_set::double_disinflation_rate::id()) {
6424 self.apply_double_disinflation_rate();
6425 }
6426
6427 self.apply_slot_time_persistent_changes();
6429 self.apply_slot_time_runtime_changes();
6430
6431 self.apply_new_builtin_program_feature_transitions(&new_feature_activations);
6432
6433 if new_feature_activations.contains(&feature_set::replace_spl_token_with_p_token::id())
6434 && let Err(e) = self.upgrade_loader_v2_program_with_loader_v3_program(
6435 &feature_set::replace_spl_token_with_p_token::SPL_TOKEN_PROGRAM_ID,
6436 &feature_set::replace_spl_token_with_p_token::PTOKEN_PROGRAM_BUFFER,
6437 self.feature_set
6438 .snapshot()
6439 .relax_programdata_account_check_migration,
6440 "replace_spl_token_with_p_token",
6441 )
6442 {
6443 warn!(
6444 "Failed to replace SPL Token with p-token buffer '{}': {e}",
6445 feature_set::replace_spl_token_with_p_token::PTOKEN_PROGRAM_BUFFER,
6446 );
6447 }
6448
6449 if new_feature_activations.contains(&feature_set::upgrade_bpf_stake_program_to_v5::id())
6450 && let Err(e) = self.upgrade_core_bpf_program(
6451 &solana_sdk_ids::stake::id(),
6452 &feature_set::upgrade_bpf_stake_program_to_v5::buffer::id(),
6453 "upgrade_stake_program_to_v5",
6454 )
6455 {
6456 error!("Failed to upgrade Core BPF Stake program: {e}");
6457 }
6458
6459 if new_feature_activations.contains(&feature_set::upgrade_bpf_stake_program_to_v5_1::id())
6460 && let Err(e) = self.upgrade_core_bpf_program(
6461 &solana_sdk_ids::stake::id(),
6462 &feature_set::upgrade_bpf_stake_program_to_v5_1::buffer::id(),
6463 "upgrade_stake_program_to_v5_1",
6464 )
6465 {
6466 error!("Failed to upgrade Core BPF Stake program: {e}");
6467 }
6468 }
6469
6470 fn apply_new_builtin_program_feature_transitions(
6471 &mut self,
6472 new_feature_activations: &AHashSet<Pubkey>,
6473 ) {
6474 for builtin in BUILTINS.iter() {
6475 if let Some(feature_id) = builtin.enable_feature_id
6476 && new_feature_activations.contains(&feature_id)
6477 {
6478 self.add_builtin(
6479 builtin.program_id,
6480 builtin.name,
6481 ProgramCacheEntry::new_builtin(builtin.register_fn),
6482 );
6483 }
6484
6485 if let Some(core_bpf_migration_config) = &builtin.core_bpf_migration_config {
6486 if new_feature_activations.contains(&core_bpf_migration_config.feature_id)
6490 && let Err(e) = self.migrate_builtin_to_core_bpf(
6491 &builtin.program_id,
6492 core_bpf_migration_config,
6493 self.feature_set
6494 .snapshot()
6495 .relax_programdata_account_check_migration,
6496 )
6497 {
6498 warn!(
6499 "Failed to migrate builtin {} to Core BPF: {}",
6500 builtin.name, e
6501 );
6502 }
6503 };
6504 }
6505
6506 for stateless_builtin in STATELESS_BUILTINS.iter() {
6510 if let Some(core_bpf_migration_config) = &stateless_builtin.core_bpf_migration_config
6511 && new_feature_activations.contains(&core_bpf_migration_config.feature_id)
6512 && let Err(e) = self.migrate_builtin_to_core_bpf(
6513 &stateless_builtin.program_id,
6514 core_bpf_migration_config,
6515 self.feature_set
6516 .snapshot()
6517 .relax_programdata_account_check_migration,
6518 )
6519 {
6520 warn!(
6521 "Failed to migrate stateless builtin {} to Core BPF: {}",
6522 stateless_builtin.name, e
6523 );
6524 }
6525 }
6526
6527 for precompile in get_precompiles() {
6528 if let Some(feature_id) = &precompile.feature
6529 && new_feature_activations.contains(feature_id)
6530 {
6531 self.add_precompile(&precompile.program_id);
6532 }
6533 }
6534 }
6535
6536 fn adjust_sysvar_balance_for_rent(&self, account: &mut AccountSharedData) {
6537 account.set_lamports(
6538 self.get_minimum_balance_for_rent_exemption(account.data().len())
6539 .max(account.lamports()),
6540 );
6541 }
6542
6543 fn compute_active_feature_set(&self, include_pending: bool) -> (FeatureSet, AHashSet<Pubkey>) {
6546 let mut active = self.feature_set.active().clone();
6547 let mut inactive = AHashSet::new();
6548 let mut pending = AHashSet::new();
6549 let slot = self.slot();
6550
6551 for feature_id in self.feature_set.inactive() {
6552 let mut activated = None;
6553 if let Some(account) = self.get_account_with_fixed_root(feature_id)
6554 && let Some(feature) = feature::state::from_account(&account)
6555 {
6556 match feature.activated_at {
6557 None if include_pending => {
6558 pending.insert(*feature_id);
6560 activated = Some(slot);
6561 }
6562 Some(activation_slot) if slot >= activation_slot => {
6563 activated = Some(activation_slot);
6565 }
6566 _ => {}
6567 }
6568 }
6569 if let Some(slot) = activated {
6570 active.insert(*feature_id, slot);
6571 } else {
6572 inactive.insert(*feature_id);
6573 }
6574 }
6575
6576 (FeatureSet::new(active, inactive), pending)
6577 }
6578
6579 pub fn compute_pending_activation_slot(&self, feature_id: &Pubkey) -> Option<Slot> {
6582 let account = self.get_account_with_fixed_root(feature_id)?;
6583 let feature = feature::from_account(&account)?;
6584 if feature.activated_at.is_some() {
6585 return None;
6587 }
6588 let active_epoch = self.epoch + 1;
6590 Some(self.epoch_schedule.get_first_slot_in_epoch(active_epoch))
6591 }
6592
6593 fn add_active_builtin_programs(&mut self) {
6594 for builtin in BUILTINS.iter() {
6595 let builtin_is_bpf = builtin.core_bpf_migration_config.is_some() && {
6612 self.get_account(&builtin.program_id)
6613 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
6614 .unwrap_or(false)
6615 };
6616
6617 if builtin_is_bpf {
6620 continue;
6621 }
6622
6623 let builtin_is_active = builtin
6624 .enable_feature_id
6625 .map(|feature_id| self.feature_set.is_active(&feature_id))
6626 .unwrap_or(true);
6627
6628 if builtin_is_active {
6629 self.transaction_processor.add_builtin(
6630 builtin.program_id,
6631 ProgramCacheEntry::new_builtin(builtin.register_fn),
6632 );
6633 }
6634 }
6635 }
6636
6637 fn add_builtin_program_accounts(&mut self) {
6638 for builtin in BUILTINS.iter() {
6639 let builtin_is_bpf = builtin.core_bpf_migration_config.is_some() && {
6656 self.get_account(&builtin.program_id)
6657 .map(|a| a.owner() == &bpf_loader_upgradeable::id())
6658 .unwrap_or(false)
6659 };
6660
6661 if builtin_is_bpf {
6664 continue;
6665 }
6666
6667 let builtin_is_active = builtin
6668 .enable_feature_id
6669 .map(|feature_id| self.feature_set.is_active(&feature_id))
6670 .unwrap_or(true);
6671
6672 if builtin_is_active {
6673 self.add_builtin_account(builtin.name, &builtin.program_id);
6674 }
6675 }
6676
6677 for precompile in get_precompiles() {
6678 let precompile_is_active = precompile
6679 .feature
6680 .as_ref()
6681 .map(|feature_id| self.feature_set.is_active(feature_id))
6682 .unwrap_or(true);
6683
6684 if precompile_is_active {
6685 self.add_precompile(&precompile.program_id);
6686 }
6687 }
6688 }
6689
6690 pub fn calculate_accounts_data_size(&self) -> ScanResult<u64> {
6698 let mut accounts_data_size: u64 = 0;
6699 self.scan_all_accounts(|address_account_slot| {
6700 let Some((_address, account, _slot)) = address_account_slot else {
6701 return;
6702 };
6703 accounts_data_size = accounts_data_size
6704 .checked_add(account.data().len() as u64)
6705 .expect("accounts data size cannot overflow");
6706 })?;
6707 Ok(accounts_data_size)
6708 }
6709
6710 pub fn is_in_slot_hashes_history(&self, slot: &Slot) -> bool {
6711 if slot < &self.slot
6712 && let Ok(slot_hashes) = self.transaction_processor.sysvar_cache().get_slot_hashes()
6713 {
6714 return slot_hashes.get(slot).is_some();
6715 }
6716 false
6717 }
6718
6719 pub fn fee_structure(&self) -> &FeeStructure {
6720 &self.fee_structure
6721 }
6722
6723 pub fn parent_block_id(&self) -> Option<Hash> {
6724 self.parent().and_then(|p| p.block_id())
6725 }
6726
6727 pub fn block_id(&self) -> Option<Hash> {
6728 *self.block_id.read().unwrap()
6729 }
6730
6731 pub fn set_block_id(&self, block_id: Option<Hash>) {
6732 let mut block_id_w = self.block_id.write().unwrap();
6733 debug_assert!(block_id_w.is_none() || *block_id_w == block_id);
6734 *block_id_w = block_id
6735 }
6736
6737 pub fn compute_budget(&self) -> Option<ComputeBudget> {
6738 self.compute_budget
6739 }
6740
6741 pub fn add_builtin(&self, program_id: Pubkey, name: &str, builtin: ProgramCacheEntry) {
6742 debug!("Adding program {name} under {program_id:?}");
6743 self.add_builtin_account(name, &program_id);
6744 self.transaction_processor.add_builtin(program_id, builtin);
6745 debug!("Added program {name} under {program_id:?}");
6746 }
6747
6748 fn add_builtin_account(&self, name: &str, program_id: &Pubkey) {
6751 let existing_genuine_program =
6752 self.get_account_with_fixed_root(program_id)
6753 .and_then(|account| {
6754 if native_loader::check_id(account.owner()) {
6758 Some(account)
6759 } else {
6760 self.burn_and_purge_account(program_id, account);
6762 None
6763 }
6764 });
6765
6766 if existing_genuine_program.is_some() {
6768 return;
6770 }
6771
6772 assert!(
6773 !self.freeze_started(),
6774 "Can't change frozen bank by adding not-existing new builtin program ({name}, \
6775 {program_id}). Maybe, inconsistent program activation is detected on snapshot \
6776 restore?"
6777 );
6778
6779 let (lamports, rent_epoch) =
6781 self.inherit_specially_retained_account_fields(&existing_genuine_program);
6782 let account: AccountSharedData = AccountSharedData::from(Account {
6783 lamports,
6784 data: name.as_bytes().to_vec(),
6785 owner: solana_sdk_ids::native_loader::id(),
6786 executable: true,
6787 rent_epoch,
6788 });
6789 self.store_account_and_update_capitalization(program_id, &account);
6790 }
6791
6792 pub fn get_bank_hash_stats(&self) -> BankHashStats {
6793 self.bank_hash_stats.load()
6794 }
6795
6796 pub fn clear_epoch_rewards_cache(&self) {
6797 self.epoch_rewards_calculation_cache.lock().unwrap().clear();
6798 }
6799
6800 pub fn set_accounts_lt_hash_for_snapshot_minimizer(&self, accounts_lt_hash: AccountsLtHash) {
6802 *self.accounts_lt_hash.lock().unwrap() = accounts_lt_hash;
6803 }
6804
6805 pub fn get_collector_fee_details(&self) -> CollectorFeeDetails {
6807 self.collector_fee_details.read().unwrap().clone()
6808 }
6809
6810 pub fn minimum_vote_account_balance_for_vat(&self) -> u64 {
6814 let vote_account_rent_exempt_minimum = self
6815 .rent_collector
6816 .rent
6817 .minimum_balance(VoteStateV4::size_of());
6818 if self.feature_set.snapshot().alpenglow {
6819 vote_account_rent_exempt_minimum + self.vat_to_burn_per_epoch()
6820 } else {
6821 vote_account_rent_exempt_minimum
6822 }
6823 }
6824
6825 pub fn get_top_epoch_stakes(&self) -> Stakes<StakeAccount<Delegation>> {
6828 self.stakes_cache.stakes().clone_and_filter_for_vat(
6829 MAX_ALPENGLOW_VOTE_ACCOUNTS,
6830 self.minimum_vote_account_balance_for_vat(),
6831 )
6832 }
6833
6834 pub fn calculate_and_set_block_id_for_dcou(bank: &Bank) {
6846 if bank.block_id().is_some() {
6847 return;
6849 }
6850
6851 let Some(parent) = bank.parent() else {
6852 bank.freeze();
6856 bank.set_block_id(Some(bank.hash()));
6857 return;
6858 };
6859
6860 let parent_block_id = parent.block_id().unwrap_or_else(|| {
6861 Self::calculate_and_set_block_id_for_dcou(&parent);
6863 parent.block_id().unwrap()
6864 });
6865
6866 bank.freeze();
6868 let block_id =
6869 solana_sha256_hasher::hashv(&[parent_block_id.as_ref(), bank.hash().as_ref()]);
6870 bank.set_block_id(Some(block_id));
6871 }
6872
6873 pub(crate) fn get_alpenglow_migration_slot(&self) -> Option<Slot> {
6874 let genesis_cert = self.get_alpenglow_genesis_certificate()?;
6875 Some(genesis_cert.block.slot)
6876 }
6877
6878 pub fn set_accounts_lt_hash_async_progress_is_at_end(&self) {
6881 self.accounts_lt_hash_async_progress.set_is_at_end_of_slot();
6882 }
6883
6884 pub fn clear_accounts_lt_hash_async_progress_is_at_end(&self) {
6888 self.accounts_lt_hash_async_progress
6889 .clear_is_at_end_of_slot();
6890 }
6891}
6892
6893impl InvokeContextCallback for Bank {
6894 fn get_epoch_stake(&self) -> u64 {
6895 self.get_current_epoch_total_stake()
6896 }
6897
6898 fn get_epoch_stake_for_vote_account(&self, vote_address: &Pubkey) -> u64 {
6899 self.get_current_epoch_vote_accounts()
6900 .get(vote_address)
6901 .map(|(stake, _)| *stake)
6902 .unwrap_or(0)
6903 }
6904
6905 fn is_precompile(&self, program_id: &Pubkey) -> bool {
6906 is_precompile(program_id, |feature_id: &Pubkey| {
6907 self.feature_set.is_active(feature_id)
6908 })
6909 }
6910
6911 fn process_precompile(
6912 &self,
6913 program_id: &Pubkey,
6914 data: &[u8],
6915 instruction_datas: Vec<&[u8]>,
6916 ) -> std::result::Result<(), PrecompileError> {
6917 if let Some(precompile) = get_precompile(program_id, |feature_id: &Pubkey| {
6918 self.feature_set.is_active(feature_id)
6919 }) {
6920 precompile.verify(data, &instruction_datas, &self.feature_set)
6921 } else {
6922 Err(PrecompileError::InvalidPublicKey)
6923 }
6924 }
6925}
6926
6927impl TransactionProcessingCallback for Bank {
6928 fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
6929 self.rc
6930 .accounts
6931 .load_with_fixed_root(&self.ancestors, pubkey, None::<fn(_, &_, _) -> _>)
6932 .map(|(account, _slot)| account)
6933 }
6934
6935 fn inspect_account(&self, _address: &Pubkey, _account_state: AccountState, _is_writable: bool) {
6936 }
6938}
6939
6940impl fmt::Debug for Bank {
6941 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6942 f.debug_struct("Bank")
6943 .field("slot", &self.slot)
6944 .field("bank_id", &self.bank_id)
6945 .field("block_height", &self.block_height)
6946 .field("parent_slot", &self.parent_slot)
6947 .field("capitalization", &self.capitalization())
6948 .finish_non_exhaustive()
6949 }
6950}
6951
6952#[cfg(feature = "dev-context-only-utils")]
6953impl Bank {
6954 fn new_from_fields_for_tests(
6961 bank_rc: BankRc,
6962 fields: BankFieldsToDeserialize,
6963 feature_set: FeatureSet,
6964 epoch_stakes: HashMap<Epoch, VersionedEpochStakes>,
6965 leader: SlotLeader,
6966 stakes_cache: StakesCache,
6967 accounts_data_size_initial: u64,
6968 ) -> Self {
6969 let slot = fields.slot;
6970 let epoch = fields.epoch_schedule.get_epoch(slot);
6971 let ancestors = Ancestors::from(vec![slot]);
6972 let rent = Self::load_rent_from_account_for_snapshot_load(&bank_rc.accounts, &ancestors);
6973
6974 let accounts = Accounts::new(Arc::clone(&bank_rc.accounts.accounts_db));
6975 let mut bank = Self::default_with_accounts(accounts);
6976
6977 bank.rc = bank_rc;
6978 bank.blockhash_queue = RwLock::new(fields.blockhash_queue);
6979 bank.ancestors = ancestors;
6980 bank.hash = RwLock::new(fields.hash);
6981 bank.parent_hash = fields.parent_hash;
6982 bank.parent_slot = fields.parent_slot;
6983 bank.hard_forks = Arc::new(RwLock::new(fields.hard_forks));
6984 bank.transaction_count = AtomicU64::new(fields.transaction_count);
6985 bank.tick_height = AtomicU64::new(fields.tick_height);
6986 bank.signature_count = AtomicU64::new(fields.signature_count);
6987 bank.capitalization = AtomicU64::new(fields.capitalization);
6988 bank.max_tick_height = fields.max_tick_height;
6989 bank.hashes_per_tick = RwLock::new(fields.hashes_per_tick);
6990 bank.ticks_per_slot = fields.ticks_per_slot;
6991 bank.ns_per_slot = fields.ns_per_slot;
6992 bank.genesis_creation_time = fields.genesis_creation_time;
6993 bank.slots_per_year = fields.slots_per_year;
6994 bank.slot = slot;
6995 bank.epoch = epoch;
6996 bank.block_height = fields.block_height;
6997 bank.leader = leader;
6998 bank.fee_rate_governor = fields.fee_rate_governor;
6999 bank.rent_collector = RentCollector::new(
7000 epoch,
7001 fields.epoch_schedule.clone(),
7002 fields.slots_per_year,
7003 rent,
7004 );
7005 bank.epoch_schedule = fields.epoch_schedule;
7006 bank.inflation = Arc::new(RwLock::new(fields.inflation));
7007 bank.stakes_cache = stakes_cache;
7008 bank.epoch_stakes = epoch_stakes;
7009 bank.is_delta = AtomicBool::new(fields.is_delta);
7010 bank.cluster_type = Some(ClusterType::Development);
7011 bank.feature_set = Arc::new(feature_set);
7012 bank.freeze_started = AtomicBool::new(fields.hash != Hash::default());
7013 bank.accounts_data_size_initial = accounts_data_size_initial;
7014 bank.transaction_processor = TransactionBatchProcessor::new_uninitialized(slot, epoch);
7015 bank.accounts_lt_hash = Mutex::new(fields.accounts_lt_hash);
7016 bank.bank_hash_stats = AtomicBankHashStats::new(&fields.bank_hash_stats);
7017 bank.refresh_slot_params_with_baseline(SlotParams::genesis_baseline(
7018 bank.ns_per_slot,
7019 bank.slots_per_year,
7020 bank.hashes_per_tick(),
7021 bank.partitioned_rewards_stake_account_stores_per_block,
7022 ));
7023
7024 bank
7025 }
7026
7027 pub fn new_for_txn_tests(
7038 bank_rc: BankRc,
7039 fields: BankFieldsToDeserialize,
7040 feature_set: FeatureSet,
7041 epoch_stakes: HashMap<Epoch, VersionedEpochStakes>,
7042 ) -> Self {
7043 let leader = SlotLeader {
7044 id: fields.leader_id,
7045 vote_address: Pubkey::default(),
7046 };
7047 let mut bank = Self::new_from_fields_for_tests(
7048 bank_rc,
7049 fields,
7050 feature_set,
7051 epoch_stakes,
7052 leader,
7053 StakesCache::default(), 0, );
7056
7057 bank.apply_activated_features();
7058 bank.transaction_processor
7059 .fill_missing_sysvar_cache_entries(&bank);
7060
7061 bank
7062 }
7063
7064 pub fn new_for_block_tests(
7074 bank_rc: BankRc,
7075 fields: BankFieldsToDeserialize,
7076 feature_set: FeatureSet,
7077 epoch_stakes: HashMap<Epoch, VersionedEpochStakes>,
7078 stakes: Stakes<StakeAccount<Delegation>>,
7079 accounts_data_size_initial: u64,
7080 ) -> Self {
7081 let parent_epoch = fields.epoch_schedule.get_epoch(fields.parent_slot);
7082 let parent_capitalization = fields.capitalization;
7083 let leader =
7084 Self::slot_leader_from_epoch_stakes(fields.slot, &fields.epoch_schedule, &epoch_stakes);
7085
7086 let mut bank = Self::new_from_fields_for_tests(
7087 bank_rc,
7088 fields,
7089 feature_set,
7090 epoch_stakes,
7091 leader,
7092 StakesCache::new(stakes),
7093 accounts_data_size_initial,
7094 );
7095
7096 bank.apply_activated_features();
7097 bank.stakes_cache.refresh_delegated_stakes(
7098 bank.new_warmup_cooldown_rate_epoch(),
7099 bank.use_fixed_point_stake_math(),
7100 );
7101
7102 bank.recalculate_partitioned_rewards_if_active(|| {
7105 rayon::ThreadPoolBuilder::new()
7106 .num_threads(1)
7107 .build()
7108 .expect("single-threaded rayon pool")
7109 });
7110
7111 bank.prepare_for_block_execution(
7112 parent_epoch,
7113 bank.parent_slot,
7114 parent_capitalization,
7115 bank.block_height.saturating_sub(1),
7116 null_tracer(),
7117 );
7118
7119 bank
7120 }
7121
7122 pub fn wrap_with_bank_forks_for_tests(self) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
7123 let bank_forks = BankForks::new_rw_arc(self);
7124 let bank = bank_forks.read().unwrap().root_bank();
7125 (bank, bank_forks)
7126 }
7127
7128 pub fn default_for_tests() -> Self {
7129 let accounts_db = AccountsDb::default_for_tests();
7130 let accounts = Accounts::new(Arc::new(accounts_db));
7131 Self::default_with_accounts(accounts)
7132 }
7133
7134 pub fn new_with_bank_forks_for_tests(
7135 genesis_config: &GenesisConfig,
7136 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
7137 let bank = Self::new_for_tests(genesis_config);
7138 bank.wrap_with_bank_forks_for_tests()
7139 }
7140
7141 pub fn new_for_tests(genesis_config: &GenesisConfig) -> Self {
7142 Self::new_with_paths_for_tests(genesis_config, None, vec![], None)
7143 }
7144
7145 pub fn new_with_mockup_builtin_for_tests(
7146 genesis_config: &GenesisConfig,
7147 program_id: Pubkey,
7148 builtin: BuiltinFunctionRegisterer,
7149 ) -> (Arc<Self>, Arc<RwLock<BankForks>>) {
7150 let mut bank = Self::new_for_tests(genesis_config);
7151 bank.add_mockup_builtin(program_id, builtin);
7152 bank.wrap_with_bank_forks_for_tests()
7153 }
7154
7155 pub fn new_with_paths_for_tests(
7156 genesis_config: &GenesisConfig,
7157 test_config: Option<BankTestConfig>,
7158 paths: Vec<PathBuf>,
7159 leader: Option<SlotLeader>,
7160 ) -> Self {
7161 let test_config = test_config.unwrap_or_default();
7162 let mut bank = Self::new_from_genesis(
7163 genesis_config,
7164 Arc::new(RuntimeConfig::default()),
7165 paths,
7166 None,
7167 test_config.accounts_db_config,
7168 None,
7169 leader,
7170 Arc::default(),
7171 None,
7172 None,
7173 );
7174 bank.set_fee_structure(&FeeStructure {
7176 lamports_per_signature: genesis_config.fee_rate_governor.lamports_per_signature,
7177 ..FeeStructure::default()
7178 });
7179 bank
7180 }
7181
7182 pub fn new_for_benches(genesis_config: &GenesisConfig) -> Self {
7183 Self::new_with_paths_for_benches(genesis_config, Vec::new())
7184 }
7185
7186 pub fn new_with_paths_for_benches(genesis_config: &GenesisConfig, paths: Vec<PathBuf>) -> Self {
7189 Self::new_from_genesis(
7190 genesis_config,
7191 Arc::<RuntimeConfig>::default(),
7192 paths,
7193 None,
7194 ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS,
7195 None,
7196 Some(SlotLeader::new_unique()),
7197 Arc::default(),
7198 None,
7199 None,
7200 )
7201 }
7202
7203 pub fn new_from_parent_with_bank_forks(
7204 bank_forks: &RwLock<BankForks>,
7205 parent: Arc<Bank>,
7206 leader: SlotLeader,
7207 slot: Slot,
7208 ) -> Arc<Self> {
7209 let bank = Bank::new_from_parent(parent, leader, slot);
7210 bank_forks
7211 .write()
7212 .unwrap()
7213 .insert(bank)
7214 .clone_without_scheduler()
7215 }
7216
7217 pub fn prepare_batch_for_tests(
7219 &self,
7220 txs: Vec<Transaction>,
7221 ) -> TransactionBatch<'_, '_, RuntimeTransaction<SanitizedTransaction>> {
7222 let sanitized_txs = txs
7223 .into_iter()
7224 .map(RuntimeTransaction::from_transaction_for_tests)
7225 .collect::<Vec<_>>();
7226 TransactionBatch::new(
7227 self.try_lock_accounts(&sanitized_txs),
7228 self,
7229 OwnedOrBorrowed::Owned(sanitized_txs),
7230 )
7231 }
7232
7233 pub fn set_accounts_data_size_initial_for_tests(&mut self, amount: u64) {
7236 self.accounts_data_size_initial = amount;
7237 }
7238
7239 pub fn update_accounts_data_size_delta_off_chain_for_tests(&self, amount: i64) {
7242 self.update_accounts_data_size_delta_off_chain(amount)
7243 }
7244
7245 #[must_use]
7251 pub fn process_transactions<'a>(
7252 &self,
7253 txs: impl Iterator<Item = &'a Transaction>,
7254 ) -> Vec<Result<()>> {
7255 self.try_process_transactions(txs).unwrap()
7256 }
7257
7258 #[must_use]
7264 pub fn process_entry_transactions(&self, txs: Vec<VersionedTransaction>) -> Vec<Result<()>> {
7265 self.try_process_entry_transactions(txs).unwrap()
7266 }
7267
7268 pub fn get_sysvar_cache_for_tests(&self) -> SysvarCache {
7269 self.transaction_processor.get_sysvar_cache_for_tests()
7270 }
7271
7272 pub fn calculate_accounts_lt_hash_for_tests(&self) -> AccountsLtHash {
7273 self.rc
7274 .accounts
7275 .accounts_db
7276 .calculate_accounts_lt_hash_at_startup_from_index(&self.ancestors)
7277 }
7278
7279 pub fn get_transaction_processor(&self) -> &TransactionBatchProcessor<BankForks> {
7280 &self.transaction_processor
7281 }
7282
7283 pub fn set_fee_structure(&mut self, fee_structure: &FeeStructure) {
7284 self.fee_structure = fee_structure.clone();
7285 }
7286
7287 pub fn load_program(
7288 &self,
7289 pubkey: &Pubkey,
7290 effective_epoch: Epoch,
7291 ) -> Option<Arc<ProgramCacheEntry>> {
7292 let environments = self
7293 .transaction_processor
7294 .program_runtime_environment_for_epoch(effective_epoch);
7295 load_program_with_pubkey(
7296 self,
7297 &environments,
7298 pubkey,
7299 self.slot(),
7300 &mut ExecuteTimings::default(), )
7302 }
7303
7304 pub fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
7305 match self.get_account_with_fixed_root(pubkey) {
7306 Some(mut account) => {
7307 let min_balance = match get_system_account_kind(&account) {
7308 Some(SystemAccountKind::Nonce) => self
7309 .rent_collector
7310 .rent
7311 .minimum_balance(nonce::state::State::size()),
7312 _ => 0,
7313 };
7314
7315 lamports
7316 .checked_add(min_balance)
7317 .filter(|required_balance| *required_balance <= account.lamports())
7318 .ok_or(TransactionError::InsufficientFundsForFee)?;
7319 account
7320 .checked_sub_lamports(lamports)
7321 .map_err(|_| TransactionError::InsufficientFundsForFee)?;
7322 self.store_account(pubkey, &account);
7323
7324 Ok(())
7325 }
7326 None => Err(TransactionError::AccountNotFound),
7327 }
7328 }
7329
7330 pub fn set_hash_overrides(&self, hash_overrides: HashOverrides) {
7331 *self.hash_overrides.lock().unwrap() = hash_overrides;
7332 }
7333
7334 pub(crate) fn get_stake_accounts(&self, minimized_account_set: &DashSet<Pubkey>) {
7336 self.stakes_cache
7337 .stakes()
7338 .stake_delegations()
7339 .iter()
7340 .for_each(|(pubkey, _)| {
7341 minimized_account_set.insert(*pubkey);
7342 });
7343
7344 self.stakes_cache
7345 .stakes()
7346 .staked_nodes()
7347 .par_iter()
7348 .for_each(|(pubkey, _)| {
7349 minimized_account_set.insert(*pubkey);
7350 });
7351 }
7352
7353 pub fn slot_time_reduction_active(&self) -> bool {
7355 self.ns_per_slot != self.slot_params.baseline_params().ns_per_slot()
7356 }
7357}
7358
7359pub(crate) fn rewards_calculation_thread_pool() -> &'static ThreadPool {
7369 static NEW_EPOCH_THREAD_POOL: OnceLock<ThreadPool> = OnceLock::new();
7370 NEW_EPOCH_THREAD_POOL.get_or_init(|| {
7371 rayon::ThreadPoolBuilder::new()
7372 .thread_name(|i| format!("solBnkClcRwds{i:02}"))
7373 .build()
7374 .expect("new epoch boundary rayon threadpool")
7375 })
7376}
7377
7378fn calculate_data_size_delta(old_data_size: usize, new_data_size: usize) -> i64 {
7381 assert!(old_data_size <= i64::MAX as usize);
7382 assert!(new_data_size <= i64::MAX as usize);
7383 let old_data_size = old_data_size as i64;
7384 let new_data_size = new_data_size as i64;
7385
7386 new_data_size.saturating_sub(old_data_size)
7387}
7388
7389impl Drop for Bank {
7390 fn drop(&mut self) {
7391 self.clear_accounts_lt_hash_async_progress_is_at_end();
7392 if let Some(drop_callback) = self.drop_callback.read().unwrap().0.as_ref() {
7393 drop_callback.callback(self);
7394 } else {
7395 self.rc
7397 .accounts
7398 .accounts_db
7399 .purge_slot(self.slot(), self.bank_id(), false);
7400 }
7401 }
7402}
7403
7404pub mod test_utils {
7406 use {
7407 super::Bank,
7408 crate::installed_scheduler_pool::BankWithScheduler,
7409 solana_account::{ReadableAccount, WritableAccount, state_traits::StateMutWincode as _},
7410 solana_instruction::error::LamportsError,
7411 solana_pubkey::Pubkey,
7412 solana_sha256_hasher::hashv,
7413 solana_vote_interface::state::VoteStateV4,
7414 solana_vote_program::vote_state::{BlockTimestamp, VoteStateVersions},
7415 std::sync::Arc,
7416 };
7417 pub fn goto_end_of_slot(bank: Arc<Bank>) {
7418 goto_end_of_slot_with_scheduler(&BankWithScheduler::new_without_scheduler(bank))
7419 }
7420
7421 pub fn goto_end_of_slot_with_scheduler(bank: &BankWithScheduler) {
7422 let mut tick_hash = bank.last_blockhash();
7423 loop {
7424 tick_hash = hashv(&[tick_hash.as_ref(), &[42]]);
7425 bank.register_tick(&tick_hash);
7426 if tick_hash == bank.last_blockhash() {
7427 bank.freeze();
7428 return;
7429 }
7430 }
7431 }
7432
7433 pub fn update_vote_account_timestamp(
7434 timestamp: BlockTimestamp,
7435 bank: &Bank,
7436 vote_pubkey: &Pubkey,
7437 ) {
7438 let mut vote_account = bank.get_account(vote_pubkey).unwrap_or_default();
7439 let mut vote_state = VoteStateV4::deserialize(vote_account.data(), vote_pubkey)
7440 .ok()
7441 .unwrap_or_default();
7442 vote_state.last_timestamp = timestamp;
7443 let versioned = VoteStateVersions::new_v4(vote_state);
7444 vote_account.set_state(&versioned).unwrap();
7445 bank.store_account(vote_pubkey, &vote_account);
7446 }
7447
7448 pub fn deposit(
7449 bank: &Bank,
7450 pubkey: &Pubkey,
7451 lamports: u64,
7452 ) -> std::result::Result<u64, LamportsError> {
7453 let mut account = bank
7456 .get_account_with_fixed_root_no_cache(pubkey)
7457 .unwrap_or_default();
7458 account.checked_add_lamports(lamports)?;
7459 bank.store_account(pubkey, &account);
7460 Ok(account.lamports())
7461 }
7462}