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